IxPersistable.h 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. /****************************************************************************
  2. **
  3. ** https://www.qxorm.com/
  4. ** Copyright (C) 2013 Lionel Marty (contact@qxorm.com)
  5. **
  6. ** This file is part of the QxOrm library
  7. **
  8. ** This software is provided 'as-is', without any express or implied
  9. ** warranty. In no event will the authors be held liable for any
  10. ** damages arising from the use of this software
  11. **
  12. ** Commercial Usage
  13. ** Licensees holding valid commercial QxOrm licenses may use this file in
  14. ** accordance with the commercial license agreement provided with the
  15. ** Software or, alternatively, in accordance with the terms contained in
  16. ** a written agreement between you and Lionel Marty
  17. **
  18. ** GNU General Public License Usage
  19. ** Alternatively, this file may be used under the terms of the GNU
  20. ** General Public License version 3.0 as published by the Free Software
  21. ** Foundation and appearing in the file 'license.gpl3.txt' included in the
  22. ** packaging of this file. Please review the following information to
  23. ** ensure the GNU General Public License version 3.0 requirements will be
  24. ** met : http://www.gnu.org/copyleft/gpl.html
  25. **
  26. ** If you are unsure which license is appropriate for your use, or
  27. ** if you have questions regarding the use of this file, please contact :
  28. ** contact@qxorm.com
  29. **
  30. ****************************************************************************/
  31. #ifndef _IX_PERSISTABLE_H_
  32. #define _IX_PERSISTABLE_H_
  33. #ifdef _MSC_VER
  34. #pragma once
  35. #endif
  36. /*!
  37. * \file IxPersistable.h
  38. * \author Lionel Marty
  39. * \ingroup QxDao
  40. * \brief Common interface (abstract class) for persistents classes using QX_PERSISTABLE_HPP() and QX_PERSISTABLE_CPP() macros
  41. */
  42. #include <QxDao/QxSqlQuery.h>
  43. #include <QxDao/QxDao.h>
  44. #include <QxDao/QxSqlSaveMode.h>
  45. #include <QxRegister/QxClass.h>
  46. #include <QxCollection/QxCollection.h>
  47. #include <QxValidator/QxInvalidValueX.h>
  48. #include <QxValidator/QxValidatorFct.h>
  49. #include <QxTraits/get_class_name.h>
  50. namespace qx {
  51. class IxPersistableCollection;
  52. /*!
  53. * \ingroup QxDao
  54. * \brief qx::IxPersistable : common interface (abstract class) for persistents classes using QX_PERSISTABLE_HPP() and QX_PERSISTABLE_CPP() macros
  55. *
  56. * To use this common interface for persistents classes : <br>
  57. * <b>1-</b> inherit your persistent class from <i>qx::IxPersistable</i> ; <br>
  58. * <b>2-</b> into your class definition (<i>myClass.h</i> for example), add <i>QX_PERSISTABLE_HPP(myClass)</i> macro ; <br>
  59. * <b>3-</b> into your class implementation (<i>myClass.cpp</i> for example), add <i>QX_PERSISTABLE_CPP(myClass)</i> macro.
  60. *
  61. * <b>Note :</b> for a list of objects (<i>qxFetchAll()</i> method or <i>qxFetchByQuery()</i> method), use <i>qx::QxCollection<type_primary_key, std::shared_ptr<my_type>></i> type.
  62. * Or just use <i>qx::QxPersistableCollectionHelper<T>::type</i> to retrieve your persistent collection type.
  63. * A convenient way to fetch a list of objects is to use following static methods <i>qxFetchAll()</i> and <i>qxFetchByQuery()</i> :
  64. * \code
  65. std::shared_ptr<qx::IxPersistableCollection> lst = qx::IxPersistable::qxFetchAll("myClass");
  66. for (long l = 0; l < lst->_count(); l++)
  67. { qx::IxPersistable_ptr ptr = lst->_get<qx::IxPersistable_ptr>(l); etc... }
  68. * \endcode
  69. */
  70. class QX_DLL_EXPORT IxPersistable
  71. {
  72. public:
  73. IxPersistable();
  74. virtual ~IxPersistable();
  75. /*!
  76. * \brief Return the number of lines in the table (database) mapped to the current C++ class (registered into QxOrm context) and filtered by a user SQL query
  77. * \param query Define a user SQL query added to default SQL query builded by QxOrm library
  78. * \param pDatabase Connection to database (you can manage your own connection pool for example, you can also define a transaction, etc.); if NULL, a valid connection for the current thread is provided by qx::QxSqlDatabase singleton class
  79. * \param relation List of relationships keys to be fetched (eager fetch instead of default lazy fetch for a relation)
  80. *
  81. * qx::IxPersistable * p = ...;<br>
  82. * p->qxCount(...) execute following SQL query :<br>
  83. * <i>SELECT COUNT(*) FROM my_table</i> + <i>XXX_JOINS_XXX</i> + <i>WHERE my_query...</i>
  84. */
  85. virtual long qxCount(const qx::QxSqlQuery & query = qx::QxSqlQuery(), QSqlDatabase * pDatabase = NULL, const QStringList & relation = QStringList()) = 0;
  86. /*!
  87. * \brief Return the number of lines in the table (database) mapped to the current C++ class (registered into QxOrm context) and filtered by a user SQL query
  88. * \param lCount Output parameter with the number of lines in the table associated to the SQL query
  89. * \param query Define a user SQL query added to default SQL query builded by QxOrm library
  90. * \param pDatabase Connection to database (you can manage your own connection pool for example, you can also define a transaction, etc.); if NULL, a valid connection for the current thread is provided by qx::QxSqlDatabase singleton class
  91. * \param relation List of relationships keys to be fetched (eager fetch instead of default lazy fetch for a relation)
  92. *
  93. * qx::IxPersistable * p = ...;<br>
  94. * p->qxCount(...) execute following SQL query :<br>
  95. * <i>SELECT COUNT(*) FROM my_table</i> + <i>XXX_JOINS_XXX</i> + <i>WHERE my_query...</i>
  96. */
  97. virtual QSqlError qxCount(long & lCount, const qx::QxSqlQuery & query = qx::QxSqlQuery(), QSqlDatabase * pDatabase = NULL, const QStringList & relation = QStringList()) = 0;
  98. /*!
  99. * \brief Fetch current instance (retrieve all its properties) mapped to a table in the database (current instance must have a valid id before to be fetched without error, or pass the id to the first parameter of this method)
  100. * \param id Unique id to fetch properties from database (if empty, check id of current instance)
  101. * \param columns List of database table columns (mapped to properties of C++ class) to fetch (if empty, all columns are fetched)
  102. * \param relation List of relationships keys to fetch (eager fetch instead of default lazy fetch for a relation) : use "|" separator to put many relationships keys into this parameter
  103. * \param pDatabase Connection to database (you can manage your own connection pool for example, you can also define a transaction, etc.); if NULL, a valid connection for the current thread is provided by qx::QxSqlDatabase singleton class
  104. * \return Empty QSqlError object (from Qt library) if no error occurred; otherwise QSqlError contains a description of database error executing SQL query
  105. *
  106. * qx::IxPersistable * p = ...;<br>
  107. * p->qxFetchById(...) execute following SQL query :<br>
  108. * <i>SELECT * FROM my_table WHERE my_id = ?</i>
  109. */
  110. virtual QSqlError qxFetchById(const QVariant & id = QVariant(), const QStringList & columns = QStringList(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) = 0;
  111. /*!
  112. * \brief Fetch a list of objects (retrieve all elements and properties associated) of current type (container registered into QxOrm context) mapped to a table in the database
  113. * \param list Container to fetch all items (retrieve all elements and properties associated); list is cleared before executing SQL query
  114. * \param columns List of database table columns (mapped to properties of C++ class) to fetch (if empty, all columns are fetched)
  115. * \param relation List of relationships keys to fetch (eager fetch instead of default lazy fetch for a relation) : use "|" separator to put many relationships keys into this parameter
  116. * \param pDatabase Connection to database (you can manage your own connection pool for example, you can also define a transaction, etc.); if NULL, a valid connection for the current thread is provided by qx::QxSqlDatabase singleton class
  117. * \return Empty QSqlError object (from Qt library) if no error occurred; otherwise QSqlError contains a description of database error executing SQL query
  118. *
  119. * qx::IxPersistable * p = ...;<br>
  120. * std::shared_ptr<qx::IxPersistableCollection> lst = p->qxNewPersistableCollection();<br>
  121. * p->qxFetchAll(& lst, ...) execute following SQL query :<br>
  122. * <i>SELECT * FROM my_table</i>
  123. */
  124. virtual QSqlError qxFetchAll(qx::IxPersistableCollection * list = NULL, const QStringList & columns = QStringList(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) = 0;
  125. /*!
  126. * \brief Fetch a list of objects (retrieve all elements and properties associated) of current type (container registered into QxOrm context) mapped to a table in the database and filtered by a user SQL query
  127. * \param query Define a user SQL query added to default SQL query builded by QxOrm library
  128. * \param list Container to fetch all items (retrieve all elements and properties associated); list is cleared before executing SQL query
  129. * \param columns List of database table columns (mapped to properties of C++ class) to fetch (if empty, all columns are fetched)
  130. * \param relation List of relationships keys to fetch (eager fetch instead of default lazy fetch for a relation) : use "|" separator to put many relationships keys into this parameter
  131. * \param pDatabase Connection to database (you can manage your own connection pool for example, you can also define a transaction, etc.); if NULL, a valid connection for the current thread is provided by qx::QxSqlDatabase singleton class
  132. * \return Empty QSqlError object (from Qt library) if no error occurred; otherwise QSqlError contains a description of database error executing SQL query
  133. *
  134. * qx::IxPersistable * p = ...;<br>
  135. * std::shared_ptr<qx::IxPersistableCollection> lst = p->qxNewPersistableCollection();<br>
  136. * p->qxFetchByQuery(my_query, & lst, ...) execute following SQL query :<br>
  137. * <i>SELECT * FROM my_table</i> + <i>WHERE my_query...</i>
  138. */
  139. virtual QSqlError qxFetchByQuery(const qx::QxSqlQuery & query, qx::IxPersistableCollection * list = NULL, const QStringList & columns = QStringList(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) = 0;
  140. /*!
  141. * \brief Insert current instance into database
  142. * \param relation List of relationships keys to insert in others tables of database : use "|" separator to put many relationships keys into this parameter
  143. * \param pDatabase Connection to database (you can manage your own connection pool for example, you can also define a transaction, etc.); if NULL, a valid connection for the current thread is provided by qx::QxSqlDatabase singleton class
  144. * \return Empty QSqlError object (from Qt library) if no error occurred; otherwise QSqlError contains a description of database error executing SQL query
  145. *
  146. * qx::IxPersistable * p = ...;<br>
  147. * p->qxInsert(...) execute following SQL query :<br>
  148. * <i>INSERT INTO my_table (my_column_1, my_column_2, etc.) VALUES (?, ?, etc.)</i>
  149. */
  150. virtual QSqlError qxInsert(const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) = 0;
  151. /*!
  152. * \brief Update current instance into database (you can add a user SQL query to the default SQL query builded by QxOrm library)
  153. * \param query Define a user SQL query added to default SQL query builded by QxOrm library
  154. * \param columns List of database table columns (mapped to properties of C++ class) to update (if empty, all columns are updated)
  155. * \param relation List of relationships keys to update in others tables of database : use "|" separator to put many relationships keys into this parameter
  156. * \param pDatabase Connection to database (you can manage your own connection pool for example, you can also define a transaction, etc.); if NULL, a valid connection for the current thread is provided by qx::QxSqlDatabase singleton class
  157. * \return Empty QSqlError object (from Qt library) if no error occurred; otherwise QSqlError contains a description of database error executing SQL query
  158. *
  159. * qx::IxPersistable * p = ...;<br>
  160. * p->qxUpdate(...) execute following SQL query :<br>
  161. * <i>UPDATE my_table SET my_column_1 = ?, my_column_2 = ?, etc.</i> + <i>WHERE my_query...</i>
  162. */
  163. virtual QSqlError qxUpdate(const qx::QxSqlQuery & query = qx::QxSqlQuery(), const QStringList & columns = QStringList(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) = 0;
  164. /*!
  165. * \brief Insert (if no exist) or update (if already exist) current instance into database
  166. * \param relation List of relationships keys to insert or update in others tables of database : use "|" separator to put many relationships keys into this parameter
  167. * \param pDatabase Connection to database (you can manage your own connection pool for example, you can also define a transaction, etc.); if NULL, a valid connection for the current thread is provided by qx::QxSqlDatabase singleton class
  168. * \param eSaveRecursiveMode Parameter to call qx::dao::save_with_relation_recursive function
  169. * \return Empty QSqlError object (from Qt library) if no error occurred; otherwise QSqlError contains a description of database error executing SQL query
  170. *
  171. * qx::IxPersistable * p = ...;<br>
  172. * p->qxSave(...) execute following SQL query :<br>
  173. * <i>INSERT INTO my_table (my_column_1, my_column_2, etc.) VALUES (?, ?, etc.)</i>
  174. * <br>or (if already exist into database) :<br>
  175. * <i>UPDATE my_table SET my_column_1 = ?, my_column_2 = ?, etc.</i>
  176. */
  177. virtual QSqlError qxSave(const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL, qx::dao::save_mode::e_save_mode eSaveRecursiveMode = qx::dao::save_mode::e_none) = 0;
  178. /*!
  179. * \brief Delete current instance from database
  180. * \param id Unique id to delete from database (if empty, check id of current instance)
  181. * \param pDatabase Connection to database (you can manage your own connection pool for example, you can also define a transaction, etc.); if NULL, a valid connection for the current thread is provided by qx::QxSqlDatabase singleton class
  182. * \return Empty QSqlError object (from Qt library) if no error occurred; otherwise QSqlError contains a description of database error executing SQL query
  183. *
  184. * qx::IxPersistable * p = ...;<br>
  185. * p->qxDeleteById(...) execute following SQL query :<br>
  186. * <i>DELETE FROM my_table WHERE my_id = ?</i><br>
  187. * <br>
  188. * If a soft delete behavior is defined for current class, p->qxDeleteById(...) execute following SQL query :<br>
  189. * <i>UPDATE my_table SET is_deleted='1' WHERE my_id = ?</i>
  190. */
  191. virtual QSqlError qxDeleteById(const QVariant & id = QVariant(), QSqlDatabase * pDatabase = NULL) = 0;
  192. /*!
  193. * \brief Delete all lines of a table (database) mapped to current C++ class (registered into QxOrm context)
  194. * \param pDatabase Connection to database (you can manage your own connection pool for example, you can also define a transaction, etc.); if NULL, a valid connection for the current thread is provided by qx::QxSqlDatabase singleton class
  195. * \return Empty QSqlError object (from Qt library) if no error occurred; otherwise QSqlError contains a description of database error executing SQL query
  196. *
  197. * qx::IxPersistable * p = ...;<br>
  198. * p->qxDeleteAll(...) execute following SQL query :<br>
  199. * <i>DELETE FROM my_table</i><br>
  200. * <br>
  201. * If a soft delete behavior is defined for current class, p->qxDeleteAll(...) execute following SQL query :<br>
  202. * <i>UPDATE my_table SET is_deleted='1'</i>
  203. */
  204. virtual QSqlError qxDeleteAll(QSqlDatabase * pDatabase = NULL) = 0;
  205. /*!
  206. * \brief Delete all lines of a table (database) mapped to current C++ class (registered into QxOrm context) and filtered by a user SQL query
  207. * \param query Define a user SQL query added to default SQL query builded by QxOrm library
  208. * \param pDatabase Connection to database (you can manage your own connection pool for example, you can also define a transaction, etc.); if NULL, a valid connection for the current thread is provided by qx::QxSqlDatabase singleton class
  209. * \return Empty QSqlError object (from Qt library) if no error occurred; otherwise QSqlError contains a description of database error executing SQL query
  210. *
  211. * qx::IxPersistable * p = ...;<br>
  212. * p->qxDeleteByQuery(...) execute following SQL query :<br>
  213. * <i>DELETE FROM my_table</i> + <i>WHERE my_query...</i><br>
  214. * <br>
  215. * If a soft delete behavior is defined for current class, p->qxDeleteByQuery(...) execute following SQL query :<br>
  216. * <i>UPDATE my_table SET is_deleted='1'</i> + <i>WHERE my_query...</i>
  217. */
  218. virtual QSqlError qxDeleteByQuery(const qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL) = 0;
  219. /*!
  220. * \brief Delete current instance from database
  221. * \param id Unique id to delete from database (if empty, check id of current instance)
  222. * \param pDatabase Connection to database (you can manage your own connection pool for example, you can also define a transaction, etc.); if NULL, a valid connection for the current thread is provided by qx::QxSqlDatabase singleton class
  223. * \return Empty QSqlError object (from Qt library) if no error occurred; otherwise QSqlError contains a description of database error executing SQL query
  224. *
  225. * qx::IxPersistable * p = ...;<br>
  226. * p->qxDestroyById(...) execute following SQL query :<br>
  227. * <i>DELETE FROM my_table WHERE my_id = ?</i><br>
  228. */
  229. virtual QSqlError qxDestroyById(const QVariant & id = QVariant(), QSqlDatabase * pDatabase = NULL) = 0;
  230. /*!
  231. * \brief Delete all lines of a table (database) mapped to current C++ class (registered into QxOrm context)
  232. * \param pDatabase Connection to database (you can manage your own connection pool for example, you can also define a transaction, etc.); if NULL, a valid connection for the current thread is provided by qx::QxSqlDatabase singleton class
  233. * \return Empty QSqlError object (from Qt library) if no error occurred; otherwise QSqlError contains a description of database error executing SQL query
  234. *
  235. * qx::IxPersistable * p = ...;<br>
  236. * p->qxDestroyAll(...) execute following SQL query :<br>
  237. * <i>DELETE FROM my_table</i><br>
  238. */
  239. virtual QSqlError qxDestroyAll(QSqlDatabase * pDatabase = NULL) = 0;
  240. /*!
  241. * \brief Delete all lines of a table (database) mapped to current C++ class (registered into QxOrm context) and filtered by a user SQL query
  242. * \param query Define a user SQL query added to default SQL query builded by QxOrm library
  243. * \param pDatabase Connection to database (you can manage your own connection pool for example, you can also define a transaction, etc.); if NULL, a valid connection for the current thread is provided by qx::QxSqlDatabase singleton class
  244. * \return Empty QSqlError object (from Qt library) if no error occurred; otherwise QSqlError contains a description of database error executing SQL query
  245. *
  246. * qx::IxPersistable * p = ...;<br>
  247. * p->qxDestroyByQuery(...) execute following SQL query :<br>
  248. * <i>DELETE FROM my_table</i> + <i>WHERE my_query...</i><br>
  249. */
  250. virtual QSqlError qxDestroyByQuery(const qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL) = 0;
  251. /*!
  252. * \brief Execute a custom SQL query or a stored procedure, all columns that can be mapped to the instance of type T will be fetched automatically
  253. * \param query Define a user SQL query added to default SQL query builded by QxOrm library
  254. * \param pDatabase Connection to database (you can manage your own connection pool for example, you can also define a transaction, etc.); if NULL, a valid connection for the current thread is provided by qx::QxSqlDatabase singleton class
  255. * \return Empty QSqlError object (from Qt library) if no error occurred; otherwise QSqlError contains a description of database error executing SQL query
  256. */
  257. virtual QSqlError qxExecuteQuery(qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL) = 0;
  258. /*!
  259. * \brief Execute a custom SQL query or a stored procedure, all columns that can be mapped to the instance of type T will be fetched automatically
  260. * \param query Define a user SQL query added to default SQL query builded by QxOrm library
  261. * \param list Container to fetch all items (retrieve all elements and properties associated); list is cleared before executing SQL query
  262. * \param pDatabase Connection to database (you can manage your own connection pool for example, you can also define a transaction, etc.); if NULL, a valid connection for the current thread is provided by qx::QxSqlDatabase singleton class
  263. * \return Empty QSqlError object (from Qt library) if no error occurred; otherwise QSqlError contains a description of database error executing SQL query
  264. */
  265. virtual QSqlError qxExecuteQuery(qx::QxSqlQuery & query, qx::IxPersistableCollection * list = NULL, QSqlDatabase * pDatabase = NULL) = 0;
  266. /*!
  267. * \brief Search if current instance already exists into database
  268. * \param id Unique id to check into database (if empty, check id of current instance)
  269. * \param pDatabase Connection to database (you can manage your own connection pool for example, you can also define a transaction, etc.); if NULL, a valid connection for the current thread is provided by qx::QxSqlDatabase singleton class
  270. * \return Return true if element already exists into database; otherwise return false; if an error occurred, qx_bool object contains a description of database error executing SQL query
  271. *
  272. * qx::IxPersistable * p = ...;<br>
  273. * p->qxExist(...) execute following SQL query :<br>
  274. * <i>SELECT * FROM my_table WHERE my_id = ?</i>
  275. */
  276. virtual qx_bool qxExist(const QVariant & id = QVariant(), QSqlDatabase * pDatabase = NULL) = 0;
  277. /*!
  278. * \brief Check if current instance is valid or not
  279. * \param groups List of groups to check (defined into QxValidator module for current class)
  280. * \return Return list of invalid values (if empty, current instance is valid)
  281. *
  282. * For more details about <b>QxValidator</b> module : https://www.qxorm.com/qxorm_en/faq.html#faq_250
  283. */
  284. virtual qx::QxInvalidValueX qxValidate(const QStringList & groups = QStringList()) = 0;
  285. /*!
  286. * \brief Create a new collection smart-pointer to fetch a list of items of current class type
  287. * \param bAsList If true, returns a list (array) of persistent instances instead of key/value hash-map
  288. * \return Return a new collection smart-pointer to fetch a list of items of current class type
  289. */
  290. virtual std::shared_ptr<qx::IxPersistableCollection> qxNewPersistableCollection(bool bAsList = false) const = 0;
  291. /*!
  292. * \brief Access to introspection engine (or reflection engine) of QxOrm library
  293. * \return Return a qx::IxClass pointer to access to introspection engine (or reflection engine) of QxOrm library, and get some informations about current class (properties, methods, etc...)
  294. */
  295. virtual qx::IxClass * qxClass() const = 0;
  296. #ifndef _QX_NO_JSON
  297. virtual QString toJson(const QString & format = QString()) const = 0;
  298. virtual QJsonValue toJson_(const QString & format = QString()) const = 0;
  299. virtual qx_bool fromJson(const QString & json, const QString & format = QString()) = 0;
  300. virtual qx_bool fromJson_(const QJsonValue & json, const QString & format = QString()) = 0;
  301. #endif // _QX_NO_JSON
  302. public:
  303. static std::shared_ptr<qx::IxPersistableCollection> qxFetchAll(const QString & className, const QStringList & columns = QStringList(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL, bool bAsList = false);
  304. static std::shared_ptr<qx::IxPersistableCollection> qxFetchByQuery(const QString & className, const qx::QxSqlQuery & query, const QStringList & columns = QStringList(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL, bool bAsList = false);
  305. static std::shared_ptr<qx::IxPersistableCollection> qxExecuteQuery(const QString & className, qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL, bool bAsList = false);
  306. };
  307. typedef std::shared_ptr<qx::IxPersistable> IxPersistable_ptr;
  308. } // namespace qx
  309. namespace qx {
  310. namespace trait {
  311. /*!
  312. * \ingroup QxTraits
  313. * \brief qx::trait::is_ix_persistable<T>::value : return true if T implements qx::IxPersistable interface, otherwise return false
  314. */
  315. template <typename T>
  316. struct is_ix_persistable
  317. { enum { value = std::is_base_of<qx::IxPersistable, T>::value }; };
  318. } // namespace trait
  319. } // namespace qx
  320. #ifndef _QX_NO_JSON
  321. #define QX_PERSISTABLE_JSON_HPP(className) \
  322. virtual QString toJson(const QString & format = QString()) const; \
  323. virtual QJsonValue toJson_(const QString & format = QString()) const; \
  324. virtual qx_bool fromJson(const QString & json, const QString & format = QString()); \
  325. virtual qx_bool fromJson_(const QJsonValue & json, const QString & format = QString());
  326. #else // _QX_NO_JSON
  327. #define QX_PERSISTABLE_JSON_HPP(className) /* Nothing */
  328. #endif // _QX_NO_JSON
  329. #define QX_PERSISTABLE_HPP(className) \
  330. public: \
  331. virtual long qxCount(const qx::QxSqlQuery & query = qx::QxSqlQuery(), QSqlDatabase * pDatabase = NULL, const QStringList & relation = QStringList()); \
  332. virtual QSqlError qxCount(long & lCount, const qx::QxSqlQuery & query = qx::QxSqlQuery(), QSqlDatabase * pDatabase = NULL, const QStringList & relation = QStringList()); \
  333. virtual QSqlError qxFetchById(const QVariant & id = QVariant(), const QStringList & columns = QStringList(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL); \
  334. virtual QSqlError qxFetchAll(qx::IxPersistableCollection * list = NULL, const QStringList & columns = QStringList(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL); \
  335. virtual QSqlError qxFetchByQuery(const qx::QxSqlQuery & query, qx::IxPersistableCollection * list = NULL, const QStringList & columns = QStringList(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL); \
  336. virtual QSqlError qxInsert(const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL); \
  337. virtual QSqlError qxUpdate(const qx::QxSqlQuery & query = qx::QxSqlQuery(), const QStringList & columns = QStringList(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL); \
  338. virtual QSqlError qxSave(const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL, qx::dao::save_mode::e_save_mode eSaveRecursiveMode = qx::dao::save_mode::e_none); \
  339. virtual QSqlError qxDeleteById(const QVariant & id = QVariant(), QSqlDatabase * pDatabase = NULL); \
  340. virtual QSqlError qxDeleteAll(QSqlDatabase * pDatabase = NULL); \
  341. virtual QSqlError qxDeleteByQuery(const qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL); \
  342. virtual QSqlError qxDestroyById(const QVariant & id = QVariant(), QSqlDatabase * pDatabase = NULL); \
  343. virtual QSqlError qxDestroyAll(QSqlDatabase * pDatabase = NULL); \
  344. virtual QSqlError qxDestroyByQuery(const qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL); \
  345. virtual QSqlError qxExecuteQuery(qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL); \
  346. virtual QSqlError qxExecuteQuery(qx::QxSqlQuery & query, qx::IxPersistableCollection * list = NULL, QSqlDatabase * pDatabase = NULL); \
  347. virtual qx_bool qxExist(const QVariant & id = QVariant(), QSqlDatabase * pDatabase = NULL); \
  348. virtual qx::QxInvalidValueX qxValidate(const QStringList & groups = QStringList()); \
  349. virtual std::shared_ptr<qx::IxPersistableCollection> qxNewPersistableCollection(bool bAsList = false) const; \
  350. virtual qx::IxClass * qxClass() const; \
  351. QX_PERSISTABLE_JSON_HPP(className)
  352. #ifdef _QX_NO_RTTI
  353. #define QX_PERSISTABLE_CAST_COLLECTION(className) \
  354. if (! list) { return QSqlError(); } \
  355. qx::QxPersistableCollectionHelper< className >::type_coll * list_typed = static_cast< qx::QxPersistableCollectionHelper< className >::type * >(list);
  356. #else // _QX_NO_RTTI
  357. #define QX_PERSISTABLE_CAST_COLLECTION(className) \
  358. if (! list) { return QSqlError(); } \
  359. qx::QxPersistableCollectionHelper< className >::type_coll * list_typed = dynamic_cast< qx::QxPersistableCollectionHelper< className >::type * >(list);
  360. #endif // _QX_NO_RTTI
  361. #ifndef _QX_NO_JSON
  362. #define QX_PERSISTABLE_JSON_CPP(className) \
  363. QString className::toJson(const QString & format) const { return qx::serialization::json::to_string((* this), 1, format); } \
  364. QJsonValue className::toJson_(const QString & format) const { return qx::cvt::to_json((* this), format); } \
  365. qx_bool className::fromJson(const QString & json, const QString & format) { return qx::serialization::json::from_string((* this), json, 1, format); } \
  366. qx_bool className::fromJson_(const QJsonValue & json, const QString & format) { return qx::cvt::from_json(json, (* this), format); }
  367. #else // _QX_NO_JSON
  368. #define QX_PERSISTABLE_JSON_CPP(className) /* Nothing */
  369. #endif // _QX_NO_JSON
  370. #define QX_PERSISTABLE_CPP(className) \
  371. \
  372. long className::qxCount(const qx::QxSqlQuery & query, QSqlDatabase * pDatabase, const QStringList & relation) \
  373. { \
  374. if (relation.count() == 0) { return qx::dao::count< className >(query, pDatabase); } \
  375. else { long lCount(0); qx::dao::count_with_relation< className >(lCount, relation, query, pDatabase); return lCount; } \
  376. } \
  377. \
  378. QSqlError className::qxCount(long & lCount, const qx::QxSqlQuery & query, QSqlDatabase * pDatabase, const QStringList & relation) \
  379. { \
  380. if (relation.count() == 0) { return qx::dao::count< className >(lCount, query, pDatabase); } \
  381. else { return qx::dao::count_with_relation< className >(lCount, relation, query, pDatabase); } \
  382. } \
  383. \
  384. QSqlError className::qxFetchById(const QVariant & id, const QStringList & columns, const QStringList & relation, QSqlDatabase * pDatabase) \
  385. { \
  386. if (id.isValid()) \
  387. { \
  388. qx::IxDataMemberX * pDataMemberX = qx::QxClass< className >::getSingleton()->getDataMemberX(); \
  389. qx::IxDataMember * pDataMemberId = (pDataMemberX ? pDataMemberX->getId_WithDaoStrategy() : NULL); \
  390. if (! pDataMemberId) { qDebug("[QxOrm] problem with 'qxFetchById()' method : '%s'", "data member id not registered"); qAssert(false); } \
  391. if (! pDataMemberId) { return QSqlError("[QxOrm] problem with 'qxFetchById()' method : 'data member id not registered'", "", QSqlError::UnknownError); } \
  392. pDataMemberId->fromVariant(this, id, -1, qx::cvt::context::e_database); \
  393. } \
  394. QSqlError err; \
  395. if (relation.count() == 0) { err = qx::dao::fetch_by_id((* this), pDatabase, columns); } \
  396. else { err = qx::dao::fetch_by_id_with_relation(relation, (* this), pDatabase); } \
  397. return err; \
  398. } \
  399. \
  400. QSqlError className::qxFetchAll(qx::IxPersistableCollection * list, const QStringList & columns, const QStringList & relation, QSqlDatabase * pDatabase) \
  401. { \
  402. QX_PERSISTABLE_CAST_COLLECTION(className) \
  403. if (! list_typed) { qDebug("[QxOrm] problem with 'qxFetchAll()' method : '%s'", "dynamic_cast failed using collection qx::QxCollection< type_primary_key, std::shared_ptr<type> >"); qAssert(false); } \
  404. if (! list_typed) { return QSqlError("[QxOrm] problem with 'qxFetchAll()' method : 'dynamic_cast failed using collection qx::QxCollection< type_primary_key, std::shared_ptr<type> >'", "", QSqlError::UnknownError); } \
  405. QSqlError err; \
  406. if (relation.count() == 0) { err = qx::dao::fetch_all((* list_typed), pDatabase, columns); } \
  407. else { err = qx::dao::fetch_all_with_relation(relation, (* list_typed), pDatabase); } \
  408. return err; \
  409. } \
  410. \
  411. QSqlError className::qxFetchByQuery(const qx::QxSqlQuery & query, qx::IxPersistableCollection * list, const QStringList & columns, const QStringList & relation, QSqlDatabase * pDatabase) \
  412. { \
  413. QX_PERSISTABLE_CAST_COLLECTION(className) \
  414. if (! list_typed) { qDebug("[QxOrm] problem with 'qxFetchByQuery()' method : '%s'", "dynamic_cast failed using collection qx::QxCollection< type_primary_key, std::shared_ptr<type> >"); qAssert(false); } \
  415. if (! list_typed) { return QSqlError("[QxOrm] problem with 'qxFetchByQuery()' method : 'dynamic_cast failed using collection qx::QxCollection< type_primary_key, std::shared_ptr<type> >'", "", QSqlError::UnknownError); } \
  416. QSqlError err; \
  417. if (relation.count() == 0) { err = qx::dao::fetch_by_query(query, (* list_typed), pDatabase, columns); } \
  418. else { err = qx::dao::fetch_by_query_with_relation(relation, query, (* list_typed), pDatabase); } \
  419. return err; \
  420. } \
  421. \
  422. QSqlError className::qxInsert(const QStringList & relation, QSqlDatabase * pDatabase) \
  423. { \
  424. QSqlError err; \
  425. if (relation.count() == 0) { err = qx::dao::insert((* this), pDatabase); } \
  426. else { err = qx::dao::insert_with_relation(relation, (* this), pDatabase); } \
  427. return err; \
  428. } \
  429. \
  430. QSqlError className::qxUpdate(const qx::QxSqlQuery & query, const QStringList & columns, const QStringList & relation, QSqlDatabase * pDatabase) \
  431. { \
  432. QSqlError err; \
  433. if (relation.count() == 0) { err = qx::dao::update_by_query(query, (* this), pDatabase, columns); } \
  434. else { err = qx::dao::update_by_query_with_relation(relation, query, (* this), pDatabase); } \
  435. return err; \
  436. } \
  437. \
  438. QSqlError className::qxSave(const QStringList & relation, QSqlDatabase * pDatabase, qx::dao::save_mode::e_save_mode eSaveRecursiveMode) \
  439. { \
  440. QSqlError err; \
  441. if (eSaveRecursiveMode != qx::dao::save_mode::e_none) { err = qx::dao::save_with_relation_recursive((* this), eSaveRecursiveMode, pDatabase); } \
  442. else if (relation.count() == 0) { err = qx::dao::save((* this), pDatabase); } \
  443. else { err = qx::dao::save_with_relation(relation, (* this), pDatabase); } \
  444. return err; \
  445. } \
  446. \
  447. QSqlError className::qxDeleteById(const QVariant & id, QSqlDatabase * pDatabase) \
  448. { \
  449. if (id.isValid()) \
  450. { \
  451. qx::IxDataMemberX * pDataMemberX = qx::QxClass< className >::getSingleton()->getDataMemberX(); \
  452. qx::IxDataMember * pDataMemberId = (pDataMemberX ? pDataMemberX->getId_WithDaoStrategy() : NULL); \
  453. if (! pDataMemberId) { qDebug("[QxOrm] problem with 'qxDeleteById()' method : '%s'", "data member id not registered"); qAssert(false); } \
  454. if (! pDataMemberId) { return QSqlError("[QxOrm] problem with 'qxDeleteById()' method : 'data member id not registered'", "", QSqlError::UnknownError); } \
  455. pDataMemberId->fromVariant(this, id, -1, qx::cvt::context::e_database); \
  456. } \
  457. return qx::dao::delete_by_id((* this), pDatabase); \
  458. } \
  459. \
  460. QSqlError className::qxDeleteAll(QSqlDatabase * pDatabase) \
  461. { \
  462. return qx::dao::delete_all< className >(pDatabase); \
  463. } \
  464. \
  465. QSqlError className::qxDeleteByQuery(const qx::QxSqlQuery & query, QSqlDatabase * pDatabase) \
  466. { \
  467. return qx::dao::delete_by_query< className >(query, pDatabase); \
  468. } \
  469. \
  470. QSqlError className::qxDestroyById(const QVariant & id, QSqlDatabase * pDatabase) \
  471. { \
  472. if (id.isValid()) \
  473. { \
  474. qx::IxDataMemberX * pDataMemberX = qx::QxClass< className >::getSingleton()->getDataMemberX(); \
  475. qx::IxDataMember * pDataMemberId = (pDataMemberX ? pDataMemberX->getId_WithDaoStrategy() : NULL); \
  476. if (! pDataMemberId) { qDebug("[QxOrm] problem with 'qxDestroyById()' method : '%s'", "data member id not registered"); qAssert(false); } \
  477. if (! pDataMemberId) { return QSqlError("[QxOrm] problem with 'qxDestroyById()' method : 'data member id not registered'", "", QSqlError::UnknownError); } \
  478. pDataMemberId->fromVariant(this, id, -1, qx::cvt::context::e_database); \
  479. } \
  480. return qx::dao::destroy_by_id((* this), pDatabase); \
  481. } \
  482. \
  483. QSqlError className::qxDestroyAll(QSqlDatabase * pDatabase) \
  484. { \
  485. return qx::dao::destroy_all< className >(pDatabase); \
  486. } \
  487. \
  488. QSqlError className::qxDestroyByQuery(const qx::QxSqlQuery & query, QSqlDatabase * pDatabase) \
  489. { \
  490. return qx::dao::destroy_by_query< className >(query, pDatabase); \
  491. } \
  492. \
  493. QSqlError className::qxExecuteQuery(qx::QxSqlQuery & query, QSqlDatabase * pDatabase) \
  494. { \
  495. return qx::dao::execute_query(query, (* this), pDatabase); \
  496. } \
  497. \
  498. QSqlError className::qxExecuteQuery(qx::QxSqlQuery & query, qx::IxPersistableCollection * list, QSqlDatabase * pDatabase) \
  499. { \
  500. QX_PERSISTABLE_CAST_COLLECTION(className) \
  501. if (! list_typed) { qDebug("[QxOrm] problem with 'qxExecuteQuery()' method : '%s'", "dynamic_cast failed using collection qx::QxCollection< type_primary_key, std::shared_ptr<type> >"); qAssert(false); } \
  502. if (! list_typed) { return QSqlError("[QxOrm] problem with 'qxExecuteQuery()' method : 'dynamic_cast failed using collection qx::QxCollection< type_primary_key, std::shared_ptr<type> >'", "", QSqlError::UnknownError); } \
  503. return qx::dao::execute_query(query, (* list_typed), pDatabase); \
  504. } \
  505. \
  506. qx_bool className::qxExist(const QVariant & id, QSqlDatabase * pDatabase) \
  507. { \
  508. if (id.isValid()) \
  509. { \
  510. qx::IxDataMemberX * pDataMemberX = qx::QxClass< className >::getSingleton()->getDataMemberX(); \
  511. qx::IxDataMember * pDataMemberId = (pDataMemberX ? pDataMemberX->getId_WithDaoStrategy() : NULL); \
  512. if (! pDataMemberId) { qDebug("[QxOrm] problem with 'qxExist()' method : '%s'", "data member id not registered"); qAssert(false); } \
  513. if (! pDataMemberId) { return qx_bool(false); } \
  514. pDataMemberId->fromVariant(this, id, -1, qx::cvt::context::e_database); \
  515. } \
  516. return qx::dao::exist((* this), pDatabase); \
  517. } \
  518. \
  519. qx::QxInvalidValueX className::qxValidate(const QStringList & groups) \
  520. { \
  521. return qx::validate((* this), groups); \
  522. } \
  523. \
  524. std::shared_ptr<qx::IxPersistableCollection> className::qxNewPersistableCollection(bool bAsList) const \
  525. { \
  526. if (bAsList) { std::shared_ptr<qx::IxPersistableCollection> coll = std::make_shared<qx::QxPersistableList< className > >(); return coll; } \
  527. else { std::shared_ptr<qx::IxPersistableCollection> coll = std::make_shared<qx::QxPersistableCollectionHelper< className >::type>(); return coll; } \
  528. } \
  529. \
  530. qx::IxClass * className::qxClass() const \
  531. { \
  532. return qx::QxClass< className >::getSingleton(); \
  533. } \
  534. \
  535. QX_PERSISTABLE_JSON_CPP(className)
  536. QX_REGISTER_CLASS_NAME(qx::IxPersistable)
  537. #include <QxDao/IxPersistableCollection.h>
  538. #endif // _IX_PERSISTABLE_H_