QxOrm  1.2.3
C++ Object Relational Mapping library
QxSqlQueryBuilder.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** http://www.qxorm.com/
00004 ** http://sourceforge.net/projects/qxorm/
00005 ** Original file by Lionel Marty
00006 **
00007 ** This file is part of the QxOrm library
00008 **
00009 ** This software is provided 'as-is', without any express or implied
00010 ** warranty. In no event will the authors be held liable for any
00011 ** damages arising from the use of this software.
00012 **
00013 ** GNU Lesser General Public License Usage
00014 ** This file must be used under the terms of the GNU Lesser
00015 ** General Public License version 2.1 as published by the Free Software
00016 ** Foundation and appearing in the file 'license.lgpl.txt' included in the
00017 ** packaging of this file.  Please review the following information to
00018 ** ensure the GNU Lesser General Public License version 2.1 requirements
00019 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
00020 **
00021 ** If you have questions regarding the use of this file, please contact :
00022 ** contact@qxorm.com
00023 **
00024 ****************************************************************************/
00025 
00026 #ifndef _QX_SQL_QUERY_BUILDER_H_
00027 #define _QX_SQL_QUERY_BUILDER_H_
00028 
00029 #ifdef _MSC_VER
00030 #pragma once
00031 #endif
00032 
00040 #include <QtCore/qmutex.h>
00041 
00042 #include <QxDao/IxSqlQueryBuilder.h>
00043 #include <QxDao/QxSqlQueryHelper.h>
00044 
00045 #include <QxRegister/QxClass.h>
00046 
00047 #include <QxTraits/remove_attr.h>
00048 #include <QxTraits/remove_smart_ptr.h>
00049 
00050 #define QX_SQL_ERR_NO_DATA_MEMBER_REGISTERED    "'QxSqlQueryBuilder<T>' error : 'qx::register_class()' not called or no data member registered"
00051 #define QX_SQL_ERR_NO_ID_REGISTERED             "'QxSqlQueryBuilder<T>' error : no id registered"
00052 
00053 #define QX_SQL_BUILDER_INIT_FCT() \
00054 static QString sql = ""; \
00055 QMutexLocker locker(& QxSqlQueryBuilder<T>::m_oMutex); \
00056 if (! sql.isEmpty()) { setSqlQuery(sql); return (* this); }
00057 
00058 #define QX_SQL_BUILDER_INIT_FCT_WITH_RELATION() \
00059 static QHash<QString, QString> sqlX; \
00060 static QHash<QString, QHash<QString, QString> > sqlAliasX; \
00061 QMutexLocker locker(& QxSqlQueryBuilder<T>::m_oMutex); \
00062 QString sql = sqlX.value(m_sHashRelation); \
00063 if (! sql.isEmpty()) { setSqlQuery(sql); m_lstSqlQueryAlias = sqlAliasX.value(m_sHashRelation); return (* this); }
00064 
00065 namespace qx {
00066 
00071 template <class T>
00072 class QxSqlQueryBuilder : public IxSqlQueryBuilder
00073 {
00074 
00075 private:
00076 
00077    typedef typename qx::trait::remove_attr<T>::type type_sql_tmp_1;
00078    typedef typename qx::trait::remove_smart_ptr<type_sql_tmp_1>::type type_sql_tmp_2;
00079 
00080 public:
00081 
00082    typedef typename qx::QxSqlQueryBuilder<T>::type_sql_tmp_2 type_sql;
00083 
00084 protected:
00085 
00086    QxDataMemberX<type_sql> * m_pDataMemberX;                         
00087 
00088    static QxCollection<QString, IxDataMember *> m_lstDataMember;     
00089    static IxSqlRelationX m_lstSqlRelation;                           
00090    static QMutex m_oMutex;                                           
00091 
00092 public:
00093 
00094    QxSqlQueryBuilder() : IxSqlQueryBuilder(), m_pDataMemberX(NULL) { ; }
00095    QxSqlQueryBuilder(const QString & sql) : IxSqlQueryBuilder(sql), m_pDataMemberX(NULL) { ; }
00096    virtual ~QxSqlQueryBuilder() { ; }
00097 
00098    virtual IxDataMemberX * getDataMemberX() const { return m_pDataMemberX; }
00099 
00100    virtual IxSqlQueryBuilder & count()
00101    {
00102       QX_SQL_BUILDER_INIT_FCT()
00103       sql = "SELECT COUNT(*) FROM " + m_sTableName;
00104       if (! m_oSoftDelete.isEmpty()) { sql += " WHERE " + m_oSoftDelete.buildSqlQueryToFetch(); }
00105       setSqlQuery(sql);
00106       return (* this);
00107    }
00108 
00109    virtual IxSqlQueryBuilder & exist()
00110    {
00111       QX_SQL_BUILDER_INIT_FCT()
00112       if (! getDataId()) { qDebug("[QxOrm] %s", QX_SQL_ERR_NO_ID_REGISTERED); qAssert(false); return (* this); }
00113       qx::dao::detail::QxSqlQueryHelper_Exist<type_sql>::sql(sql, (* this));
00114       setSqlQuery(sql);
00115       return (* this);
00116    }
00117 
00118    virtual IxSqlQueryBuilder & fetchAll()
00119    {
00120       QX_SQL_BUILDER_INIT_FCT()
00121       qx::dao::detail::QxSqlQueryHelper_FetchAll<type_sql>::sql(sql, (* this));
00122       setSqlQuery(sql);
00123       return (* this);
00124    }
00125 
00126    virtual IxSqlQueryBuilder & fetchById()
00127    {
00128       QX_SQL_BUILDER_INIT_FCT()
00129       if (! getDataId()) { qDebug("[QxOrm] %s", QX_SQL_ERR_NO_ID_REGISTERED); qAssert(false); return (* this); }
00130       qx::dao::detail::QxSqlQueryHelper_FetchById<type_sql>::sql(sql, (* this));
00131       setSqlQuery(sql);
00132       return (* this);
00133    }
00134 
00135    virtual IxSqlQueryBuilder & insert()
00136    {
00137       QX_SQL_BUILDER_INIT_FCT()
00138       qx::dao::detail::QxSqlQueryHelper_Insert<type_sql>::sql(sql, (* this));
00139       setSqlQuery(sql);
00140       return (* this);
00141    }
00142 
00143    virtual IxSqlQueryBuilder & update()
00144    {
00145       QX_SQL_BUILDER_INIT_FCT()
00146       if (! getDataId()) { qDebug("[QxOrm] %s", QX_SQL_ERR_NO_ID_REGISTERED); qAssert(false); return (* this); }
00147       qx::dao::detail::QxSqlQueryHelper_Update<type_sql>::sql(sql, (* this));
00148       setSqlQuery(sql);
00149       return (* this);
00150    }
00151 
00152    virtual IxSqlQueryBuilder & deleteAll()
00153    {
00154       QX_SQL_BUILDER_INIT_FCT()
00155       sql = "DELETE FROM " + m_sTableName;
00156       setSqlQuery(sql);
00157       return (* this);
00158    }
00159 
00160    virtual IxSqlQueryBuilder & softDeleteAll()
00161    {
00162       QX_SQL_BUILDER_INIT_FCT()
00163       if (! m_oSoftDelete.isEmpty()) { sql = "UPDATE " + m_sTableName + " SET " + m_oSoftDelete.buildSqlQueryToUpdate(); }
00164       else { qAssert(false); }
00165       setSqlQuery(sql);
00166       return (* this);
00167    }
00168 
00169    virtual IxSqlQueryBuilder & deleteById()
00170    {
00171       QX_SQL_BUILDER_INIT_FCT()
00172       if (! getDataId()) { qDebug("[QxOrm] %s", QX_SQL_ERR_NO_ID_REGISTERED); qAssert(false); return (* this); }
00173       qx::dao::detail::QxSqlQueryHelper_DeleteById<type_sql>::sql(sql, (* this), false);
00174       setSqlQuery(sql);
00175       return (* this);
00176    }
00177 
00178    virtual IxSqlQueryBuilder & softDeleteById()
00179    {
00180       QX_SQL_BUILDER_INIT_FCT()
00181       if (! getDataId()) { qDebug("[QxOrm] %s", QX_SQL_ERR_NO_ID_REGISTERED); qAssert(false); return (* this); }
00182       if (m_oSoftDelete.isEmpty()) { qAssert(false); return (* this); }
00183       qx::dao::detail::QxSqlQueryHelper_DeleteById<type_sql>::sql(sql, (* this), true);
00184       setSqlQuery(sql);
00185       return (* this);
00186    }
00187 
00188    virtual IxSqlQueryBuilder & createTable()
00189    {
00190       QX_SQL_BUILDER_INIT_FCT()
00191       qx::dao::detail::QxSqlQueryHelper_CreateTable<type_sql>::sql(sql, (* this));
00192       setSqlQuery(sql);
00193       return (* this);
00194    }
00195 
00196    virtual IxSqlQueryBuilder & fetchAll_WithRelation(IxSqlRelationX * pRelationX)
00197    {
00198       QX_SQL_BUILDER_INIT_FCT_WITH_RELATION()
00199       qx::dao::detail::QxSqlQueryHelper_FetchAll_WithRelation<type_sql>::sql(pRelationX, sql, (* this));
00200       if (! m_sHashRelation.isEmpty()) { sqlX.insert(m_sHashRelation, sql); }
00201       if (! m_sHashRelation.isEmpty()) { sqlAliasX.insert(m_sHashRelation, m_lstSqlQueryAlias); }
00202       setSqlQuery(sql);
00203       return (* this);
00204    }
00205 
00206    virtual IxSqlQueryBuilder & fetchById_WithRelation(IxSqlRelationX * pRelationX)
00207    {
00208       QX_SQL_BUILDER_INIT_FCT_WITH_RELATION()
00209       if (! getDataId()) { qDebug("[QxOrm] %s", QX_SQL_ERR_NO_ID_REGISTERED); qAssert(false); return (* this); }
00210       qx::dao::detail::QxSqlQueryHelper_FetchById_WithRelation<type_sql>::sql(pRelationX, sql, (* this));
00211       if (! m_sHashRelation.isEmpty()) { sqlX.insert(m_sHashRelation, sql); }
00212       if (! m_sHashRelation.isEmpty()) { sqlAliasX.insert(m_sHashRelation, m_lstSqlQueryAlias); }
00213       setSqlQuery(sql);
00214       return (* this);
00215    }
00216 
00217    virtual IxSqlQueryBuilder & fetchAll(const QStringList & columns)
00218    {
00219       QString sql;
00220       if (columns.count() <= 0) { return fetchAll(); }
00221       if (columns.at(0) == "*") { return fetchAll(); }
00222       if (! verifyColumns(columns)) { qAssert(false); return (* this); }
00223       qx::dao::detail::QxSqlQueryHelper_FetchAll<type_sql>::sql(sql, (* this), columns);
00224       setSqlQuery(sql);
00225       return (* this);
00226    }
00227 
00228    virtual IxSqlQueryBuilder & fetchById(const QStringList & columns)
00229    {
00230       QString sql;
00231       if (columns.count() <= 0) { return fetchById(); }
00232       if (columns.at(0) == "*") { return fetchById(); }
00233       if (! verifyColumns(columns)) { qAssert(false); return (* this); }
00234       if (! getDataId()) { qDebug("[QxOrm] %s", QX_SQL_ERR_NO_ID_REGISTERED); qAssert(false); return (* this); }
00235       qx::dao::detail::QxSqlQueryHelper_FetchById<type_sql>::sql(sql, (* this), columns);
00236       setSqlQuery(sql);
00237       return (* this);
00238    }
00239 
00240    virtual IxSqlQueryBuilder & update(const QStringList & columns)
00241    {
00242       QString sql;
00243       if (columns.count() <= 0) { return update(); }
00244       if (columns.at(0) == "*") { return update(); }
00245       if (! verifyColumns(columns)) { qAssert(false); return (* this); }
00246       if (! getDataId()) { qDebug("[QxOrm] %s", QX_SQL_ERR_NO_ID_REGISTERED); qAssert(false); return (* this); }
00247       qx::dao::detail::QxSqlQueryHelper_Update<type_sql>::sql(sql, (* this), columns);
00248       setSqlQuery(sql);
00249       return (* this);
00250    }
00251 
00252    virtual void init()
00253    {
00254       QMutexLocker locker(& QxSqlQueryBuilder<T>::m_oMutex);
00255       m_pDataMemberX = QxClass<type_sql>::getSingleton()->dataMemberX();
00256       m_pDataMemberId = m_pDataMemberX->getId_WithDaoStrategy();
00257       m_sTableName = m_pDataMemberX->getName();
00258       m_lstDataMemberPtr = (& QxSqlQueryBuilder<T>::m_lstDataMember);
00259       m_lstSqlRelationPtr = (& QxSqlQueryBuilder<T>::m_lstSqlRelation);
00260       m_oSoftDelete = QxClass<type_sql>::getSingleton()->getSoftDelete();
00261       if (getDataCount() > 0 || getRelationCount() > 0) { return; }
00262       IxDataMember * p = NULL; long lCount = m_pDataMemberX->count_WithDaoStrategy();
00263       for (long l = 0; l < lCount; ++l) { if ((p = isValid_DataMember(l))) { m_lstDataMember.insert(p->getKey(), p); } }
00264       for (long l = 0; l < lCount; ++l) { if ((p = isValid_SqlRelation(l))) { m_lstSqlRelation.insert(p->getKey(), p->getSqlRelation()); } }
00265    }
00266 
00267 private:
00268 
00269    IxDataMember * isValid_DataMember(long lIndex) const
00270    {
00271       IxDataMember * p = m_pDataMemberX->get_WithDaoStrategy(lIndex);
00272       bool bValid = (p && p->getDao() && ! p->hasSqlRelation());
00273       bValid = (bValid && (p != m_pDataMemberId));
00274       return (bValid ? p : NULL);
00275    }
00276 
00277    IxDataMember * isValid_SqlRelation(long lIndex) const
00278    {
00279       IxDataMember * p = m_pDataMemberX->get_WithDaoStrategy(lIndex);
00280       bool bIsValid = (p && p->getDao() && p->hasSqlRelation());
00281       if (bIsValid) { p->getSqlRelation()->init(); }
00282       return (bIsValid ? p : NULL);
00283    }
00284 
00285 private:
00286 
00287 #ifndef NDEBUG
00288    inline bool verifyColumns(const QStringList & columns) const
00289    {
00290       if (! m_pDataMemberX) { return false; }
00291       for (int i = 0; i < columns.count(); i++)
00292       { if (! m_pDataMemberX->exist_WithDaoStrategy(columns.at(i))) { return false; } }
00293       return true;
00294    }
00295 #else
00296    inline bool verifyColumns(const QStringList & columns) const
00297    { Q_UNUSED(columns); return true; }
00298 #endif // NDEBUG
00299 
00300 };
00301 
00302 template <class T> QMutex QxSqlQueryBuilder<T>::m_oMutex(QMutex::Recursive);
00303 template <class T> QxCollection<QString, IxDataMember *> QxSqlQueryBuilder<T>::m_lstDataMember;
00304 template <class T> IxSqlRelationX QxSqlQueryBuilder<T>::m_lstSqlRelation;
00305 
00306 } // namespace qx
00307 
00308 #endif // _QX_SQL_QUERY_BUILDER_H_