commit 506067a2376bc70badb37ff4b7a97c5d1f8d4668
Author: Christian Ehringfeld <c.ehringfeld@t-online.de>
Date:   Thu Aug 6 22:49:50 2015 +0200

    some improvements

diff --git a/EntityManager.pro b/EntityManager.pro
index 38be334..577110b 100644
--- a/EntityManager.pro
+++ b/EntityManager.pro
@@ -28,7 +28,6 @@ src/entity.h \
     src/query.h \
     src/join.h \
     src/queryinterpreter.h \
-    src/condition.h \
     src/expression.h \
     src/orderby.h
 
@@ -52,7 +51,6 @@ src/entity.cpp \
     src/query.cpp \
     src/join.cpp \
     src/queryinterpreter.cpp \
-    src/condition.cpp \
     src/expression.cpp \
     src/orderby.cpp
 
diff --git a/samples/example/main.cpp b/samples/example/main.cpp
index 3627266..8c90fd0 100644
--- a/samples/example/main.cpp
+++ b/samples/example/main.cpp
@@ -19,7 +19,7 @@ int main(int argc, char *argv[]) {
     t.start();
     CuteEntityManager::EntityManager *e = new
     CuteEntityManager::EntityManager("QSQLITE",
-                                     QDir::currentPath() + "/db.sqlite","","","",0,true);
+                                     QDir::currentPath() + "/db.sqlite", "", "", "", 0, true);
 //                CuteEntityManager::EntityManager("QSQLITE",
 //                                                     ":memory:");
 
@@ -68,19 +68,18 @@ int main(int argc, char *argv[]) {
      * ---------------------------------
      */
     qDebug() << "-----------------------------";
-    QSharedPointer<Entity> groupFindPtr = e->findById<Group *>(1);
-    QSharedPointer<Group> grp = groupFindPtr.objectCast<Group>();
+    QSharedPointer<Group> groupFindPtr = e->findById<Group>(1);
     qDebug() << "Group:" << groupFindPtr->toString();
-    qDebug() << "PersonSize:" << grp->getPersons().size();
-    qDebug() << "PupilsSize:" << grp->getPupils().size();
-    qDebug() << "MainTeacher:" << grp->getMainTeacher()->toString();
+    qDebug() << "PersonSize:" << groupFindPtr->getPersons().size();
+    qDebug() << "PupilsSize:" << groupFindPtr->getPupils().size();
+    qDebug() << "MainTeacher:" << groupFindPtr->getMainTeacher()->toString();
 
     /** ---------------------------------
      * FIND Person
      * ---------------------------------
      */
     qDebug() << "-----------------------------";
-    QSharedPointer<Entity> personFindPtr = e->findById(1, QString("Person*"));
+    QSharedPointer<Entity> personFindPtr = e->findById(1, QString("Person"));
     e->refresh(personFindPtr);
     QSharedPointer<Person> pers = personFindPtr.objectCast<Person>();
     qDebug() << "MainTeacher:" << personFindPtr->toString();
@@ -91,8 +90,8 @@ int main(int argc, char *argv[]) {
      * or you can use this syntax:
      */
     qDebug() << "-----------------------------";
-    QSharedPointer<Person> foundMainTeacher = e->findById<Person *>
-            (1).objectCast<Person>();
+    QSharedPointer<Person> foundMainTeacher = e->findById<Person>
+            (1);
     qDebug() << "FoundMainTeacher:" << foundMainTeacher->toString();
     qDebug() << "FoundMainTeacherGroupSize:" <<
              foundMainTeacher->getMaintainedGroups().size();
diff --git a/src/condition.cpp b/src/condition.cpp
deleted file mode 100644
index f718118..0000000
--- a/src/condition.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2015 Christian Ehringfeld <c.ehringfeld@t-online.de>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "condition.h"
-using namespace CuteEntityManager;
-Condition::Condition() {
-
-}
-
-Condition::Condition(QString condition) {
-    if (!condition.isEmpty()) {
-        this->conditions.append(condition);
-    }
-}
-
-void Condition::appendCondition(const QString &value) {
-    this->conditions.append(value);
-}
-
-QStringList Condition::getConditions() const {
-    return conditions;
-}
-
-void Condition::setConditions(const QStringList &value) {
-    conditions = value;
-}
-
-QList<Condition> Condition::getSubConditions() const {
-    return subConditions;
-}
-
-void Condition::setSubConditions(const QList<Condition> &value) {
-    subConditions = value;
-}
-
-void CuteEntityManager::Condition::addSubCondition(const
-        CuteEntityManager::Condition &value) {
-    this->subConditions.append(value);
-}
diff --git a/src/condition.h b/src/condition.h
deleted file mode 100644
index 7ad7406..0000000
--- a/src/condition.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2015 Christian Ehringfeld <c.ehringfeld@t-online.de>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef CONDITION_H
-#define CONDITION_H
-
-#include <QStringList>
-namespace CuteEntityManager {
-class Condition {
-  public:
-    Condition();
-    Condition(QString condition);
-    void appendCondition(const QString &value);
-    QStringList getConditions() const;
-    void setConditions(const QStringList &value);
-
-    void addSubCondition(const Condition &value);
-    QList<Condition> getSubConditions() const;
-    void setSubConditions(const QList<Condition> &value);
-
-  private:
-    QStringList conditions;
-    QList<Condition> subConditions;
-};
-}
-
-#endif // CONDITION_H
diff --git a/src/entitymanager.cpp b/src/entitymanager.cpp
index 5a5fc80..299f772 100644
--- a/src/entitymanager.cpp
+++ b/src/entitymanager.cpp
@@ -124,6 +124,28 @@ void EntityManager::setSchema(const QSharedPointer<Schema> &value) {
     schema = value;
 }
 
+QList<QHash<QString, QVariant> > EntityManager::selectByQuery(Query &query) {
+    QSqlQuery q = this->queryInterpreter->build(query);
+    return this->convertQueryResult(q);
+}
+
+QList<QHash<QString, QVariant> > EntityManager::selectBySql(
+    const QString &sql) {
+    QSqlQuery q = this->db->select(sql);
+    return this->convertQueryResult(q);
+}
+
+qint8 EntityManager::count(Query &query) {
+    qint8 rc = 0;
+    query.appendSelect("COUNT(*)");
+    QSqlQuery q = this->queryInterpreter->build(query);
+    this->db->select(q);
+    if (q.next()) {
+        rc = q.value(0).toInt();
+    }
+    return rc;
+}
+
 QString EntityManager::createConnection() {
     QStringList l = EntityManager::getConnectionNames();
     QString conName = "";
@@ -772,8 +794,8 @@ bool EntityManager::createTable(const QSharedPointer<Entity> &entity,
             createRelationTables);
 }
 
-qint8 EntityManager::count(const QSharedPointer<Entity> &entity,
-                           bool ignoreID) {
+quint8 EntityManager::count(const QSharedPointer<Entity> &entity,
+                            bool ignoreID) {
     qint8 rc = -1;
     QSqlQuery q = this->schema->getQueryBuilder()->count(entity,
                   ignoreID);
@@ -784,7 +806,7 @@ qint8 EntityManager::count(const QSharedPointer<Entity> &entity,
     return rc;
 }
 
-qint8 EntityManager::count(const QString &tableName) {
+quint8 EntityManager::count(const QString &tableName) {
     qint8 rc = -1;
     QSqlQuery q = this->schema->getQueryBuilder()->count(tableName);
     this->db->select(q);
diff --git a/src/entitymanager.h b/src/entitymanager.h
index 3084fb8..b8e0260 100644
--- a/src/entitymanager.h
+++ b/src/entitymanager.h
@@ -31,6 +31,7 @@
 #include "database.h"
 #include "entityinstancefactory.h"
 #include "cache.h"
+#include "queryinterpreter.h"
 
 namespace CuteEntityManager {
 
@@ -74,84 +75,82 @@ class EntityManager : public QObject {
     bool removeAll(QString tblname);
     bool createTable(const QSharedPointer<Entity> &entity,
                      bool createRelationTables = true);
-    qint8 count(const QSharedPointer<Entity> &entity, bool ignoreID = true);
-    qint8 count(const QString &tableName);
+    quint8 count(const QSharedPointer<Entity> &entity, bool ignoreID = true);
+    quint8 count(const QString &tableName);
     QSharedPointer<Database> getDb() const;
     void setDb(const QSharedPointer<Database> &value);
     QSharedPointer<Schema> getSchema() const;
     void refresh(QSharedPointer<Entity> &entity);
     void setSchema(const QSharedPointer<Schema> &value);
-    /**
-     *@TODO use conditions
-     */
-  public:
-    template<class T> qint8 count(QHash<QString, QString> condition =
-                                      QHash<QString, QVariant>()) {
-        Entity *e = EntityInstanceFactory::createInstance<T>();
-        qint8 rc = 0;
-        if (e) {
-            rc = this->count(e->getTablename());
-            delete e;
-        }
-        return rc;
-    }
+    QList<QHash<QString, QVariant> > selectByQuery(Query &query);
+    QList<QHash<QString, QVariant> > selectBySql(const QString &sql);
+    qint8 count(Query &query);
+
 
-    template<class T> QList<QSharedPointer<Entity>> findAll() {
+  public:
+    template<class T> QList<QSharedPointer<T>> findAll() {
         QSharedPointer<Entity> ptr = QSharedPointer<Entity>
-                                     (EntityInstanceFactory::createInstance<T>());
+                                     (EntityInstanceFactory::createInstance<T *>());
         if (ptr) {
             auto maps = this->findAll(ptr);
-            return this->convert(maps, EntityHelper::getClassname(ptr.data()));
+            auto converted = this->convert(maps, EntityHelper::getClassname(ptr.data()));
+            return this->convertList<T>(converted);
         }
-        return QList<QSharedPointer<Entity>>();
+        return QList<QSharedPointer<T>>();
     }
 
-    template<class T> QSharedPointer<Entity> findById(const qint64 &id) {
-        auto e = EntityInstanceFactory::createInstance<T>();
+    template<class T> QSharedPointer<T> findById(const qint64 &id) {
+        auto e = EntityInstanceFactory::createInstance<T *>();
         QSharedPointer<Entity> ptr = QSharedPointer<Entity>(e);
-        return this->findById(id, ptr);
+        return this->findById(id, ptr).objectCast<T>();
     }
 
-    template<class T> QSharedPointer<Entity> findEntityByAttributes(
+    template<class T> QSharedPointer<T> findEntityByAttributes(
         const QHash<QString, QVariant>
         &attributes) {
-        auto list = this->findAllEntitiesByAttributes<T>(attributes, 1, 0);
+        auto list = this->findAllEntitiesByAttributes<T *>(attributes, 1, 0);
         if (list.isEmpty()) {
-            return QSharedPointer<Entity>();
+            return QSharedPointer<T>();
         }
-        return list.at(0);
+        QSharedPointer<Entity> obj = list.at(0);
+        return obj.objectCast<T>();
     }
 
-    template<class T> QList<QSharedPointer<Entity>> findAllEntitiesByAttributes(
-                const QHash<QString, QVariant> &attributes =
-    QHash<QString, QString>(), quint32 limit = 0, quint32 offset = 0) {
-        QSharedPointer<Entity> e = QSharedPointer<Entity>
-                                   (EntityInstanceFactory::createInstance<T>());
+    template<class T> QList<QSharedPointer<T>> findAllEntitiesByAttributes(
+            const QHash<QString, QVariant> &attributes =
+    QHash<QString, QString>(), quint64 limit = 0, quint64 offset = 0) {
+        QSharedPointer<T> e = QSharedPointer<T>
+                              (EntityInstanceFactory::createInstance<T *>());
         if (e) {
-            auto results = this->findAllByAttributes(attributes, e->getTablename());
+            Query query = Query(QStringList(e->getTablename()),
+                                this->schema->getQueryBuilder()->where(attributes));
+            query.setLimit(limit);
+            query.setOffset(offset);
+            QSqlQuery q = this->queryInterpreter->build(query);
+            this->db->select(q);
+            auto results = this->convertQueryResult(q);
             auto list = this->convert(results, EntityHelper::getClassname(e.data()));
-            return list;
+            return this->convertList<T>(list);
         }
         return QList<QSharedPointer<Entity>>();
     }
 
-    template<class T> QList<QSharedPointer<Entity>> findEntitiesBySql(
+    template<class T> QList<QSharedPointer<T>> findEntitiesBySql(
     const QString &sql) {
-        Entity *e = EntityInstanceFactory::createInstance<T>();
+        QSharedPointer<T> e = EntityInstanceFactory::createInstance<T *>();
         if (e) {
-            QSqlQuery q = this->db.data()->select(sql);
+            QSqlQuery q = this->db->select(sql);
             auto result = this->convertQueryResult(q);
-            auto ret = this->convert(result, EntityHelper::getClassname(e));
-            delete e;
-            return ret;
+            auto converted = this->convert(result, EntityHelper::getClassname(e));
+            return this->convertList<T>(converted);
         }
-        return QList<QSharedPointer<Entity>>();
+        return QList<QSharedPointer<T>>();
     }
 
     template<class T> bool remove(const QList<qint64> &ids) {
         bool ok = true;
         foreach (qint64 var, ids) {
-            if (!this->remove<T>(var)) {
+            if (!this->remove<T *>(var)) {
                 ok = false;
                 break;
             }
@@ -160,7 +159,7 @@ class EntityManager : public QObject {
     }
 
     template<class T> bool remove(qint64 id) {
-        Entity *e = EntityInstanceFactory::createInstance<T>();
+        Entity *e = EntityInstanceFactory::createInstance<T *>();
         if (e) {
             QSharedPointer<Entity> ptr = QSharedPointer<Entity>(e);
             ptr->setId(id);
@@ -170,6 +169,15 @@ class EntityManager : public QObject {
     }
 
   protected:
+    template<class T> QList<QSharedPointer<T>> convertList(const
+    QList<QSharedPointer<Entity>> &list) {
+        QList<QSharedPointer<T>> newList = QList<QSharedPointer<T>>();
+        for (int i = 0; i < list.size(); ++i) {
+            newList.append(list.at(i).objectCast<T>());
+        }
+        return newList;
+    }
+
     void init();
     QList<QHash<QString, QVariant> > findAll(const QSharedPointer<Entity> &e);
     void resolveRelations(const QSharedPointer<Entity> &entity,
diff --git a/src/expression.cpp b/src/expression.cpp
index e1dc7bc..2b02f6d 100644
--- a/src/expression.cpp
+++ b/src/expression.cpp
@@ -3,9 +3,15 @@ using namespace CuteEntityManager;
 Expression::Expression() {
 }
 
-Expression::Expression(QString expression,
+Expression::Expression(QString expression, QHash<QString, QVariant> params,
                        bool onlyColumn) {
     this->expression = expression;
+    this->params = params;
+    this->onlyColumn = onlyColumn;
+}
+
+Expression::Expression(QString expression, bool onlyColumn) {
+    this->expression = expression;
     this->onlyColumn = onlyColumn;
 }
 
@@ -29,3 +35,16 @@ void Expression::setOnlyColumn(bool value) {
     onlyColumn = value;
 }
 
+void Expression::addParam(const QString &key, const QVariant &value) {
+    this->params.insert(key, value);
+}
+
+QHash<QString, QVariant> Expression::getParams() const {
+    return params;
+}
+
+void Expression::setParams(const QHash<QString, QVariant> &value) {
+    params = value;
+}
+
+
diff --git a/src/expression.h b/src/expression.h
index d85c8ff..6d487f5 100644
--- a/src/expression.h
+++ b/src/expression.h
@@ -23,8 +23,9 @@ namespace CuteEntityManager {
 class Expression {
   public:
     Expression();
-    Expression(QString expression,
+    explicit Expression(QString expression,QHash<QString, QVariant> params = QHash<QString, QVariant>(),
                bool onlyColumn = false);
+    explicit Expression(QString expression, bool onlyColumn);
     QString getExpression() const;
     void setExpression(const QString &value);
 
@@ -33,8 +34,13 @@ class Expression {
     bool getOnlyColumn() const;
     void setOnlyColumn(bool value);
 
-  private:
+    void addParam(const QString &key, const QVariant &value);
+    QHash<QString, QVariant> getParams() const;
+    void setParams(const QHash<QString, QVariant> &value);
+
+private:
     QString expression;
+    QHash<QString, QVariant> params;
     bool onlyColumn;
 };
 }
diff --git a/src/join.cpp b/src/join.cpp
index 9ed03a0..d4da472 100644
--- a/src/join.cpp
+++ b/src/join.cpp
@@ -20,15 +20,15 @@ Join::Join() {
 
 }
 
-Join::Join(QString foreignTable, QString condition, QString type) {
+Join::Join(QString foreignTable, QString expression, QString type) {
     this->foreignTable = foreignTable;
-    this->condition = Condition(condition);
+    this->expression = Expression(expression);
     this->type = type;
 }
 
-Join::Join(QString foreignTable, Condition condition, QString type) {
+Join::Join(QString foreignTable, Expression expression, QString type) {
     this->foreignTable = foreignTable;
-    this->condition = condition;
+    this->expression = expression;
     this->type = type;
 }
 
@@ -48,20 +48,10 @@ void Join::setForeignTable(const QString &value) {
     foreignTable = value;
 }
 
-Condition Join::getCondition() const {
-    return condition;
+Expression Join::getExpression() const {
+    return expression;
 }
 
-QString Join::getMainCondition() const {
-    auto conditions = this->condition.getConditions();
-    if (!conditions.isEmpty()) {
-        return conditions.at(0);
-    } else {
-        return "";
-    }
+void Join::setExpression(const Expression &value) {
+    expression = value;
 }
-
-void Join::setCondition(const Condition &value) {
-    condition = value;
-}
-
diff --git a/src/join.h b/src/join.h
index 2b758e0..0ed32ea 100644
--- a/src/join.h
+++ b/src/join.h
@@ -16,15 +16,15 @@
 #ifndef JOIN_H
 #define JOIN_H
 #include <QString>
-#include "condition.h"
+#include "expression.h"
 namespace CuteEntityManager {
 class Join {
   public:
     Join();
-    explicit Join(QString foreignTable, QString condition,
-         QString type = QStringLiteral("LEFT JOIN"));
-    explicit Join(QString foreignTable, Condition condition,
-         QString type = QStringLiteral("LEFT JOIN"));
+    explicit Join(QString foreignTable, QString expression,
+                  QString type = QStringLiteral("LEFT JOIN"));
+    explicit Join(QString foreignTable, Expression expression,
+                  QString type = QStringLiteral("LEFT JOIN"));
 
     QString getType() const;
     void setType(const QString &value);
@@ -32,14 +32,13 @@ class Join {
     QString getForeignTable() const;
     void setForeignTable(const QString &value);
 
-    Condition getCondition() const;
-    QString getMainCondition() const;
-    void setCondition(const Condition &value);
+    Expression getExpression() const;
+    void setExpression(const Expression &value);
 
-private:
+  private:
     QString type = QStringLiteral("LEFT JOIN");
     QString foreignTable;
-    Condition condition;
+    Expression expression;
 
 };
 }
diff --git a/src/query.cpp b/src/query.cpp
index 67fcff1..0670ad7 100644
--- a/src/query.cpp
+++ b/src/query.cpp
@@ -15,18 +15,33 @@
  */
 
 #include "query.h"
-#include "condition.h"
 #include "orderby.h"
 using namespace CuteEntityManager;
 Query::Query() {
     //this->select << Expression("*");
 }
 
-void Query::appendWhereCondition(const QString &condition) {
-    this->where.append(Condition(condition));
+Query::Query(QStringList from, QList<Expression> where, QList<Join> joins,
+             QHash<QString, QVariant> params, quint64 limit, quint64 offset,
+             QList<Expression> select, QStringList groupBy, bool distinct,
+             QList<Expression> having) {
+    this->from = from;
+    this->where = where;
+    this->joins = joins;
+    this->params = params;
+    this->limit = limit;
+    this->offset = offset;
+    this->select = select;
+    this->groupBy = groupBy;
+    this->distinct = distinct;
+    this->having = having;
 }
 
-void Query::appendWhereCondition(const Condition &condition) {
+void Query::appendWhere(const QString &condition) {
+    this->where.append(Expression(condition));
+}
+
+void Query::appendWhere(const Expression &condition) {
     this->where.append(condition);
 }
 
@@ -36,6 +51,22 @@ void Query::setSelect(const QStringList &value) {
     }
 }
 
+QList<Expression> Query::getWhere() const {
+    return where;
+}
+
+void Query::setWhere(const QList<Expression> &value) {
+    where = value;
+}
+
+QList<Expression> Query::getHaving() const {
+    return having;
+}
+
+void Query::setHaving(const QList<Expression> &value) {
+    having = value;
+}
+
 QString Query::getSelectOption() const {
     return selectOption;
 }
@@ -68,6 +99,10 @@ void Query::setGroupBy(const QStringList &value) {
     groupBy = value;
 }
 
+QList<Expression> Query::getSelect() const {
+    return this->select;
+}
+
 void Query::appendSelect(const Expression &value) {
     this->select.append(value);
 }
@@ -88,6 +123,12 @@ void Query::appendParam(const QString &column, QVariant value) {
     this->params.insert(column, value);
 }
 
+void Query::appendParams(const QHash<QString, QVariant> &params) {
+    for (auto i = params.constBegin(); i != params.constEnd(); ++i) {
+        this->params.insert(i.key(), i.value());
+    }
+}
+
 QHash<QString, QVariant> Query::getParams() const {
     return params;
 }
@@ -96,46 +137,30 @@ void Query::setParams(const QHash<QString, QVariant> &value) {
     params = value;
 }
 
-uint Query::getLimit() const {
+quint64 Query::getLimit() const {
     return limit;
 }
 
-void Query::setLimit(const uint &value) {
+void Query::setLimit(const quint64 &value) {
     limit = value;
 }
 
-uint Query::getOffset() const {
+quint64 Query::getOffset() const {
     return offset;
 }
 
-void Query::setOffset(const uint &value) {
+void Query::setOffset(const quint64 &value) {
     offset = value;
 }
 
-void Query::appendHavingCondition(const QString &condition) {
-    this->having.append(Condition(condition));
+void Query::appendHaving(const QString &condition) {
+    this->having.append(Expression(condition));
 }
 
-void Query::appendHavingCondition(const Condition &condition) {
+void Query::appendHaving(const Expression &condition) {
     this->having.append(condition);
 }
 
-QList<Condition> Query::getWhere() const {
-    return where;
-}
-
-void Query::setWhere(const QList<Condition> &value) {
-    where = value;
-}
-
-QList<Condition> Query::getHaving() const {
-    return having;
-}
-
-void Query::setHaving(const QList<Condition> &value) {
-    having = value;
-}
-
 void Query::appendOrderBy(const OrderBy &orderBy) {
     this->orderBy.append(orderBy);
 }
diff --git a/src/query.h b/src/query.h
index afd0b1c..5cd8421 100644
--- a/src/query.h
+++ b/src/query.h
@@ -29,6 +29,13 @@ enum class Direction;
 class Query {
   public:
     Query();
+    Query(QStringList from, QList<Expression> where,
+          QList<Join> joins = QList<Join>(),
+          QHash<QString, QVariant> params = QHash<QString, QVariant>(), quint64 limit = 0,
+          quint64 offset = 0,
+          QList<Expression> select = QList<Expression>(),
+          QStringList groupBy = QStringList(), bool distinct = false,
+          QList<Expression> having = QList<Expression>());
 
     QString getSelectOption() const;
     void setSelectOption(const QString &value);
@@ -43,26 +50,21 @@ class Query {
     void setJoins(const QList<Join> &value);
 
     void appendParam(const QString &column, QVariant value);
+    void appendParams(const QHash<QString, QVariant> &params);
     QHash<QString, QVariant> getParams() const;
     void setParams(const QHash<QString, QVariant> &value);
 
-    uint getLimit() const;
-    void setLimit(const uint &value);
+    quint64 getLimit() const;
+    void setLimit(const quint64 &value);
 
-    uint getOffset() const;
-    void setOffset(const uint &value);
+    quint64 getOffset() const;
+    void setOffset(const quint64 &value);
 
-    void appendWhereCondition(const QString &condition);
-    void appendWhereCondition(const Condition &condition);
+    void appendWhere(const QString &condition);
+    void appendWhere(const Expression &condition);
 
-    void appendHavingCondition(const QString &condition);
-    void appendHavingCondition(const Condition &condition);
-
-    QList<Condition> getWhere() const;
-    void setWhere(const QList<Condition> &value);
-
-    QList<Condition> getHaving() const;
-    void setHaving(const QList<Condition> &value);
+    void appendHaving(const QString &condition);
+    void appendHaving(const Expression &condition);
 
     void appendOrderBy(const OrderBy &orderBy);
     void appendOrderBy(const QString &column, const Direction &direction);
@@ -78,6 +80,12 @@ class Query {
     void setSelect(const QList<Expression> &value);
     void setSelect(const QStringList &value);
 
+    QList<Expression> getWhere() const;
+    void setWhere(const QList<Expression> &value);
+
+    QList<Expression> getHaving() const;
+    void setHaving(const QList<Expression> &value);
+
   private:
     QList<Expression> select;
     QString selectOption = QStringLiteral("");
@@ -85,12 +93,12 @@ class Query {
     QStringList from;
     QStringList groupBy;
     QList<OrderBy> orderBy;
-    QList<Condition> where;
-    QList<Condition> having;
+    QList<Expression> where;
+    QList<Expression> having;
     QList<Join> joins;
     QHash<QString, QVariant> params;
-    uint limit = 0;
-    uint offset = 0;
+    quint64 limit = 0;
+    quint64 offset = 0;
 };
 
 enum class JokerPosition {
diff --git a/src/querybuilder.cpp b/src/querybuilder.cpp
index e780b41..b5453f0 100644
--- a/src/querybuilder.cpp
+++ b/src/querybuilder.cpp
@@ -843,9 +843,10 @@ QString QueryBuilder::countKeyword() const {
     return "COUNT";
 }
 
-QString QueryBuilder::inFunction(Query &q, QString column,
-                                 QList<QVariant> values, bool notOp) {
+Expression QueryBuilder::inFunction(QString column,
+                                    QList<QVariant> values, bool notOp) {
     QString condition = "";
+    Expression exp = Expression();
     if (!values.isEmpty()) {
         bool first = true;
         condition = this->schema->quoteColumnName(column) + " " + this->appendNot(
@@ -859,11 +860,12 @@ QString QueryBuilder::inFunction(Query &q, QString column,
             }
             QString paramName = column + "_in" + var;
             condition += this->placeHolder(paramName);
-            q.appendParam(paramName, values.at(var));
+            exp.addParam(paramName, values.at(var));
         }
         condition += ")";
     }
-    return condition;
+    exp.setExpression(condition);
+    return exp;
 }
 
 QString QueryBuilder::between(QString colName, QString valName1,
@@ -1164,9 +1166,9 @@ void QueryBuilder::ClassAttributes::setPk(const QString &value) {
     pk = value;
 }
 
-void QueryBuilder::andOperator(Query &query,
-                               QHash<QString, QVariant> conditions) {
+Expression QueryBuilder::andOperator(QHash<QString, QVariant> conditions) {
     bool first = true;
+    Expression exp = Expression();
     QString condition = "";
     for (auto var = conditions.constBegin(); var != conditions.constEnd(); ++var) {
         if (first) {
@@ -1176,53 +1178,57 @@ void QueryBuilder::andOperator(Query &query,
         }
         condition += this->schema->quoteColumnName(var.key()) + " = " +
                      this->placeHolder(var.key());
-        query.appendParam(var.key(), var.value());
+        exp.addParam(var.key(), var.value());
     }
-    query.appendWhereCondition(condition);
+    exp.setExpression(condition);
+    return exp;
 }
 
-void QueryBuilder::arbitraryOperator(Query &query, QString op, QString column,
-                                     QVariant value) {
-    query.appendWhereCondition(this->schema->quoteColumnName(
-                                   column) + " " + op + " " +
-                               this->placeHolder(column));
-    query.appendParam(column, value);
+Expression QueryBuilder::arbitraryOperator(QString op, QString column,
+        QVariant value) {
+    Expression exp = Expression(this->schema->quoteColumnName(
+                                    column) + " " + op + " " +
+                                this->placeHolder(column));
+    exp.addParam(column, value);
+    return exp;
+
 }
 
-void QueryBuilder::isNull(Query &query, QString column) {
-    query.appendWhereCondition(this->schema->quoteColumnName(column) + " IS NULL");
+Expression QueryBuilder::isNull(QString column) {
+    return Expression(this->schema->quoteColumnName(column) + " IS NULL");
 }
 
-void QueryBuilder::isNotNull(Query &query, QString column) {
-    query.appendWhereCondition(this->schema->quoteColumnName(column) + " IS " +
-                               this->notKeyword() + " NULL");
+Expression QueryBuilder::isNotNull(QString column) {
+    return Expression(this->schema->quoteColumnName(column) + " IS " +
+                      this->notKeyword() + " NULL");
 }
 
-void QueryBuilder::plainOr(Query &query) {
-    query.appendWhereCondition(this->orKeyword());
+Expression QueryBuilder::plainOr() {
+    return Expression(this->orKeyword());
 }
 
-void QueryBuilder::plainNor(Query &query) {
-    query.appendWhereCondition(this->notKeyword() + " " + this->orKeyword());
+Expression QueryBuilder::plainNor() {
+    return Expression(this->notKeyword() + " " + this->orKeyword());
 }
 
-void QueryBuilder::plainAnd(Query &query) {
-    query.appendWhereCondition(this->andKeyword());
+Expression QueryBuilder::plainAnd() {
+    return Expression(this->andKeyword());
 }
 
-void QueryBuilder::plainNand(Query &query) {
-    query.appendWhereCondition(this->notKeyword() + " " +  this->andKeyword());
+Expression QueryBuilder::plainNand() {
+    return Expression(this->notKeyword() + " " +  this->andKeyword());
 }
 
-void QueryBuilder::like(Query &query, QString column, QVariant value,
-                        JokerPosition jp, QChar wildcard) {
-    this->arbitraryOperator(query, this->likeKeyword(), column,
-                            this->addWildcard(value, jp, wildcard));
+Expression QueryBuilder::like(QString column, QVariant value,
+                              JokerPosition jp, QChar wildcard) {
+    return Expression(this->arbitraryOperator(this->likeKeyword(), column,
+                      this->addWildcard(value, jp, wildcard)));
 }
 
-void QueryBuilder::like(Query &query, QHash<QString, QVariant> conditions,
-                        QString conjunction,
-                        JokerPosition jp, QChar wildcard) {
+Expression QueryBuilder::like(QHash<QString, QVariant> conditions,
+                              QString conjunction,
+                              JokerPosition jp, QChar wildcard) {
+    Expression exp = Expression();
     QString condition = "(";
     if (!conditions.isEmpty()) {
         bool first = true;
@@ -1236,72 +1242,77 @@ void QueryBuilder::like(Query &query, QHash<QString, QVariant> conditions,
                          + " " +
                          this->placeHolder(i.key());
             QString newVal = this->addWildcard(i.value(), jp, wildcard);
-            query.appendParam(i.key(), newVal.isEmpty() ? i.value() : newVal);
+            exp.addParam(i.key(), newVal.isEmpty() ? i.value() : newVal);
         }
         condition += ")";
-        query.appendWhereCondition(condition);
+        exp.setExpression(condition);
     }
+    return exp;
 }
 
-void QueryBuilder::where(Query &query, QString column, QVariant value) {
+Expression QueryBuilder::where(QString column, QVariant value) {
     QString placeholder = column + "_where";
-    query.appendWhereCondition(this->schema->quoteColumnName(column) + "=" +
-                               this->placeHolder(placeholder));
-    query.appendParam(placeholder, value);
+    Expression exp = Expression(this->schema->quoteColumnName(column) + "=" +
+                                this->placeHolder(placeholder));
+    exp.addParam(placeholder, value);
+    return exp;
 }
 
-void QueryBuilder::where(Query &query, QHash<QString, QVariant> conditions,
-                         QString conjunction) {
-    QString condition = this->where(conditions, conjunction, false, "id", false);
+Expression QueryBuilder::where(QHash<QString, QVariant> conditions,
+                               QString conjunction) {
+    Expression exp = Expression(this->where(conditions, conjunction, false, "id",
+                                            false));
     for (auto i = conditions.constBegin(); i != conditions.constEnd(); ++i) {
-        query.appendParam(i.key(), i.value());
+        exp.addParam(i.key(), i.value());
     }
-    query.appendWhereCondition(condition);
+    return exp;
 }
 
-void QueryBuilder::where(Query &query, QString condition,
-                         QHash<QString, QVariant> values) {
-    query.appendWhereCondition(condition);
+Expression QueryBuilder::where(QString condition,
+                               QHash<QString, QVariant> values) {
+    Expression exp = Expression(condition);
     for (auto i = values.constBegin(); i != values.constEnd(); ++i) {
-        query.appendParam(i.key(), i.value());
+        exp.addParam(i.key(), i.value());
     }
+    return exp;
 }
 
-void QueryBuilder::between(Query &query, QString column, QVariant firstValue,
-                           QVariant secondValue) {
+Expression QueryBuilder::between(QString column, QVariant firstValue,
+                                 QVariant secondValue) {
     QString firstPh = column + "_bet1";
     QString secondPh = column + "_bet2";
-    this->appendCondition(query, firstPh, secondPh, firstValue, secondValue,
-                          this->between(column, firstPh, secondPh));
+    return this->appendCondition(firstPh, secondPh, firstValue, secondValue,
+                                 this->between(column, firstPh, secondPh));
 }
 
-void QueryBuilder::notBetween(Query &query, QString column, QVariant firstValue,
-                              QVariant secondValue) {
+Expression QueryBuilder::notBetween(QString column, QVariant firstValue,
+                                    QVariant secondValue) {
     QString firstPh = column + "_nbet1";
     QString secondPh = column + "_nbet2";
-    this->appendCondition(query, firstPh, secondPh, firstValue, secondValue,
-                          this->between(column, firstPh, secondPh, true));
+    return this->appendCondition(firstPh, secondPh, firstValue, secondValue,
+                                 this->between(column, firstPh, secondPh, true));
 }
 
 
-void QueryBuilder::appendCondition(Query &q, QString ph1, QString ph2,
-                                   QVariant val1, QVariant val2, QString condition) {
-    q.appendParam(ph1, val1);
-    q.appendParam(ph2, val2);
-    q.appendWhereCondition(condition);
+Expression QueryBuilder::appendCondition(QString ph1, QString ph2,
+        QVariant val1, QVariant val2, QString condition) {
+    Expression exp = Expression(condition);
+    exp.addParam(ph1, val1);
+    exp.addParam(ph2, val2);
+    return exp;
 }
 
-void QueryBuilder::in(Query &query, QString column, QList<QVariant> values) {
-    query.appendWhereCondition(this->inFunction(query, column, values));
+Expression QueryBuilder::in(QString column, QList<QVariant> values) {
+    return this->inFunction(column, values);
 }
 
-void QueryBuilder::notIn(Query &query, QString column, QList<QVariant> values) {
-    query.appendWhereCondition(this->inFunction(query, column,
-                               values, true));
+Expression QueryBuilder::notIn(QString column, QList<QVariant> values) {
+    return this->inFunction(column, values, true);
 }
 
-void QueryBuilder::orOperator(Query &query,
-                              QHash<QString, QVariant> conditions, bool like) {
+Expression QueryBuilder::orOperator(
+    QHash<QString, QVariant> conditions, bool like) {
+    Expression exp = Expression();
     if (!conditions.isEmpty()) {
         QString condition = "(";
         bool first = true;
@@ -1314,11 +1325,12 @@ void QueryBuilder::orOperator(Query &query,
             condition += this->schema->quoteColumnName(i.key()) + (like ? " " +
                          this->likeKeyword() + " " : "=") +
                          this->placeHolder(i.key());
-            query.appendParam(i.key(), i.value());
+            exp.addParam(i.key(), i.value());
         }
         condition += ")";
-        query.appendWhereCondition(condition);
+        exp.setExpression(condition);
     }
+    return exp;
 }
 
 QString QueryBuilder::where(const QSharedPointer<Entity> &entity,
diff --git a/src/querybuilder.h b/src/querybuilder.h
index c8e9e6c..9051e12 100644
--- a/src/querybuilder.h
+++ b/src/querybuilder.h
@@ -24,11 +24,11 @@
 #include <QMetaProperty>
 #include "relation.h"
 #include "query.h"
+#include "expression.h"
 namespace CuteEntityManager {
 class Schema;
 class Entity;
 class Database;
-
 enum DbForeignKeyCascade {
     RESTRICT,
     CASCADE,
@@ -104,28 +104,28 @@ class QueryBuilder {
                     bool ignoreID = false, const QString &primaryKey = "id") const;
     void bindValue(const QString &key, const QVariant &value, QSqlQuery &q) const;
     virtual QString placeHolder(const QString &key) const;
-    void where(Query &query, QString column, QVariant value);
+    Expression where(QString column, QVariant value);
     /**
      * @brief where
      * @param query
      * @param conditions
      * @param conjunction its AND or OR
      */
-    void where(Query &query, QHash<QString, QVariant> conditions,
+    Expression where(QHash<QString, QVariant> conditions,
                QString conjunction = "AND");
-    void where(Query &query, QString condition,
+    Expression where(QString condition,
                QHash<QString, QVariant> values = QHash<QString, QVariant>());
     //void where(Query &query,QHash<QString, QList<QVariant>> conditions, QString concat="AND");
-    void between(Query &query, QString column, QVariant firstValue,
+    Expression between(QString column, QVariant firstValue,
                  QVariant secondValue);
-    void notBetween(Query &query, QString column, QVariant firstValue,
+    Expression notBetween(QString column, QVariant firstValue,
                     QVariant secondValue);
-    void in(Query &query, QString column, QList<QVariant> values);
-    void notIn(Query &query, QString column, QList<QVariant> values);
-    void notOperator(Query &query, QString column, QVariant value);
-    void orOperator(Query &query, QHash<QString, QVariant> conditions,
+    Expression in(QString column, QList<QVariant> values);
+    Expression notIn(QString column, QList<QVariant> values);
+    Expression notOperator(QString column, QVariant value);
+    Expression orOperator(QHash<QString, QVariant> conditions,
                     bool like = false);
-    void andOperator(Query &query, QHash<QString, QVariant> conditions);
+    Expression andOperator(QHash<QString, QVariant> conditions);
     /**
      * @brief arbitraryOperator
      * @param query
@@ -133,29 +133,29 @@ class QueryBuilder {
      * @param column
      * @param value
      */
-    void arbitraryOperator(Query &query, QString op, QString column,
+    Expression arbitraryOperator(QString op, QString column,
                            QVariant value);
-    void isNull(Query &query, QString column);
-    void isNotNull(Query &query, QString column);
+    Expression isNull(QString column);
+    Expression isNotNull(QString column);
 
-    void plainOr(Query &query); //adds a simple OR to condition
-    void plainNor(Query &query);
-    void plainAnd(Query &query); //add a simple AND to condition
-    void plainNand(Query &query);
+    Expression plainOr(); //adds a simple OR to condition
+    Expression plainNor();
+    Expression plainAnd(); //add a simple AND to condition
+    Expression plainNand();
     /**
      * Generates 'foo' LIKE "%bar%"
      * @brief like
      * @param column
      * @param value
      */
-    void like(Query &q, QString column, QVariant value,
+    Expression like(QString column, QVariant value,
               JokerPosition jp = JokerPosition::BOTH, QChar wildcard = '%');
     /**
      * @brief like
      * @param condition
      * @param concat
      */
-    void like(Query &query, QHash<QString, QVariant> conditions,
+    Expression like(QHash<QString, QVariant> conditions,
               QString conjunction = "AND",
               JokerPosition jp = JokerPosition::BOTH, QChar wildcard = '%');
 
@@ -286,7 +286,7 @@ class QueryBuilder {
     virtual QString inKeyword() const;
     virtual QString whereKeyword() const;
     virtual QString countKeyword() const;
-    virtual QString inFunction(Query &q, QString column, QList<QVariant> values,
+    virtual Expression inFunction(QString column, QList<QVariant> values,
                                bool notOp = false);
     virtual QString between(QString colName, QString valName1, QString valName2,
                             bool notOp = false);
@@ -294,7 +294,7 @@ class QueryBuilder {
     virtual QString limitKeyword() const;
     virtual QString offsetKeyword() const;
     QString appendNot(bool notOp);
-    virtual void appendCondition(Query &q, QString ph1, QString ph2, QVariant val1,
+    virtual Expression appendCondition(QString ph1, QString ph2, QVariant val1,
                                  QVariant val2, QString condition);
     QString entityClassname() const;
     QString separator;
diff --git a/src/queryinterpreter.cpp b/src/queryinterpreter.cpp
index cac8df0..1a6b3d2 100644
--- a/src/queryinterpreter.cpp
+++ b/src/queryinterpreter.cpp
@@ -15,7 +15,6 @@
  */
 
 #include "queryinterpreter.h"
-#include "condition.h"
 #include "join.h"
 #include "query.h"
 #include "querybuilder.h"
@@ -86,7 +85,6 @@ QString QueryInterpreter::buildSelect(const QList<Expression> &columns,
             re.optimize();
             QRegularExpressionMatchIterator iterator = re.globalMatch(nExp, 0,
                     QRegularExpression::PartialPreferFirstMatch);
-
             if (iterator.hasNext()) {
                 for (int var = 0; var < 2; ++var) {
                     QRegularExpressionMatch match = iterator.next();
@@ -96,7 +94,6 @@ QString QueryInterpreter::buildSelect(const QList<Expression> &columns,
                                                  QString::number(i));
                     }
                 }
-
             } else {
                 nExp = this->builder->getSchema()->quoteColumnName(nExp);
             }
@@ -135,17 +132,14 @@ QString QueryInterpreter::buildJoin(const QList<Join> &joins) const {
         Join j = joins.at(i);
         sqlJoin += j.getType() + this->builder->getSeparator() +
                    this->builder->getSchema()->quoteTableName(j.getForeignTable());
-        if (!j.getCondition().getConditions().isEmpty()) {
-            QString condition = this->buildCondition(j.getCondition());
-            if (!condition.isEmpty()) {
-                sqlJoin += " ON " + condition;
-            }
+        if (!j.getExpression().getExpression().isEmpty()) {
+            sqlJoin += " ON " + j.getExpression().getExpression();
         }
     }
     return sqlJoin;
 }
 
-QString QueryInterpreter::buildWhere(const QList<Condition> &conditions)
+QString QueryInterpreter::buildWhere(const QList<Expression> &conditions)
 const {
     QString where = this->buildCondition(conditions);
     return where.isEmpty() ? "" : ("WHERE " + where);
@@ -156,7 +150,7 @@ QString QueryInterpreter::buildGroupBy(const QStringList &groupBy) const {
                groupBy);
 }
 
-QString QueryInterpreter::buildHaving(const QList<Condition> &conditions)
+QString QueryInterpreter::buildHaving(const QList<Expression> &conditions)
 const {
     QString having = this->buildCondition(conditions);
     return having.isEmpty() ? "" : ("HAVING " + having);
@@ -208,15 +202,24 @@ QString QueryInterpreter::buildOrderBy(const QList<OrderBy> &columns) const {
     return sqlOrder;
 }
 
-QString QueryInterpreter::buildCondition(const QList<Condition> &conditions)
+QString QueryInterpreter::buildCondition(const QList<Expression> &conditions)
 const {
     if (conditions.isEmpty()) {
         return "";
     }
-    return "";
-}
-
-QString QueryInterpreter::buildCondition(const Condition &conditions) const {
-    return "";
+    QString sqlCondition = "";
+    bool first = true;
+    for (int i = 0; i < conditions.size(); ++i) {
+        Expression exp = conditions.at(i);
+        QString expression = exp.getExpression();
+        if (!expression.isEmpty()) {
+            if (first) {
+                first = false;
+            } else if (expression.at(0) != ' ') {
+                sqlCondition += this->builder->getSeparator();
+            }
+        }
+        sqlCondition += expression;
+    }
+    return sqlCondition;
 }
-
diff --git a/src/queryinterpreter.h b/src/queryinterpreter.h
index 971e41d..a5ec087 100644
--- a/src/queryinterpreter.h
+++ b/src/queryinterpreter.h
@@ -22,7 +22,6 @@
 namespace CuteEntityManager {
 class Query;
 class QueryBuilder;
-class Condition;
 class Join;
 class OrderBy;
 class Expression;
@@ -32,58 +31,24 @@ class QueryInterpreter {
     QSqlQuery build(const Query &q);
 
   protected:
-    QString buildSelect(const QList<Expression> &columns, const bool &distinct = false,
+    QString buildSelect(const QList<Expression> &columns,
+                        const bool &distinct = false,
                         const QString &selectOption = "") const;
     QString buildFrom(const QStringList &from) const;
     QString buildJoin(const QList<Join> &joins) const;
-    QString buildWhere(const QList<Condition> &conditions) const;
+    QString buildWhere(const QList<Expression> &conditions) const;
     QString buildGroupBy(const QStringList &groupBy) const;
-    QString buildHaving(const QList<Condition> &conditions) const;
+    QString buildHaving(const QList<Expression> &conditions) const;
     QString buildOrderByAndLimit(QString sql, const QList<OrderBy> &orderBy,
                                  const quint64 &limit, const quint64 &offset) const;
     QString buildOrderBy(const QList<OrderBy> &columns) const;
-    QString buildCondition(const QList<Condition> &conditions) const;
-    QString buildCondition(const Condition &conditions) const;
+    QString buildCondition(const QList<Expression> &conditions) const;
 
   private:
     QSharedPointer<QueryBuilder> builder;
 
 };
 
-
-
-
-//QStringList select;
-//QString selectOption = QStringLiteral("");
-//bool distinct = false;
-//QStringList from;
-//QStringList groupBy;
-//QStringList orderBy;
-//QLinkedList<Condition> conditions;
-//QList<Join> joins;
-//QHash<QString, QVariant> params;
-//uint limit = 0;
-//uint offset = 0;
-
-
-
-//protected $conditionBuilders = [
-//       'NOT' => 'buildNotCondition',
-//       'AND' => 'buildAndCondition',
-//       'OR' => 'buildAndCondition',
-//       'BETWEEN' => 'buildBetweenCondition',
-//       'NOT BETWEEN' => 'buildBetweenCondition',
-//       'IN' => 'buildInCondition',
-//       'NOT IN' => 'buildInCondition',
-//       'LIKE' => 'buildLikeCondition',
-//       'NOT LIKE' => 'buildLikeCondition',
-//       'OR LIKE' => 'buildLikeCondition',
-//       'OR NOT LIKE' => 'buildLikeCondition',
-//       'EXISTS' => 'buildExistsCondition',
-//       'NOT EXISTS' => 'buildExistsCondition',
-//   ];
-
-
 }
 
 #endif // QUERYINTERPRETER_H
