commit 1b167b6c3d5f033447e1bd5329b85a0c70580545
Author: Christian Ehringfeld <c.ehringfeld@t-online.de>
Date:   Thu Aug 6 23:20:31 2015 +0200

    improvements

diff --git a/src/entitymanager.cpp b/src/entitymanager.cpp
index 299f772..f18920b 100644
--- a/src/entitymanager.cpp
+++ b/src/entitymanager.cpp
@@ -27,6 +27,10 @@ QStringList EntityManager::getConnectionNames() {
     return EntityManager::connectionNames;
 }
 
+QSharedPointer<QueryBuilder> EntityManager::getQueryBuilder() const {
+    return this->schema->getQueryBuilder();
+}
+
 EntityManager::EntityManager(QSqlDatabase database) : QObject() {
     auto db = new Database(database);
     this->db = QSharedPointer<Database>(db);
diff --git a/src/entitymanager.h b/src/entitymanager.h
index b8e0260..ab6143c 100644
--- a/src/entitymanager.h
+++ b/src/entitymanager.h
@@ -42,20 +42,6 @@ class EntityManager : public QObject {
     Q_OBJECT
   signals:
     void actionFinished(qint64 id);
-  public:
-    EntityManager(QSqlDatabase database);
-    EntityManager(const QString &databaseType, QString databasename = "" ,
-                  QString hostname = "",
-                  QString username = "",
-                  QString password = "", QString port = "", bool logQueries = false);
-    ~EntityManager();
-    static QStringList getConnectionNames();
-    /**
-     * @brief startup
-     * @param version must be unique
-     * @param toInitialize list of entity classnames which database tables should be created
-     * @return
-     */
   public slots:
     bool startup(QString version, QStringList toInitialize);
     bool executeQuery(const QString &query);
@@ -88,6 +74,39 @@ class EntityManager : public QObject {
 
 
   public:
+public:
+  EntityManager(QSqlDatabase database);
+  EntityManager(const QString &databaseType, QString databasename = "" ,
+                QString hostname = "",
+                QString username = "",
+                QString password = "", QString port = "", bool logQueries = false);
+  ~EntityManager();
+  static QStringList getConnectionNames();
+  /**
+   * @brief startup
+   * @param version must be unique
+   * @param toInitialize list of entity classnames which database tables should be created
+   * @return
+   */
+  QSharedPointer<QueryBuilder> getQueryBuilder() const;
+
+    template<class T> QList<QSharedPointer<T>> find(Query &q) {
+        QSharedPointer<Entity> ptr = QSharedPointer<Entity>
+                                     (EntityInstanceFactory::createInstance<T *>());
+        if (ptr) {
+            if (q.getFrom().isEmpty()) {
+                q.setFrom(QStringList(ptr->getTablename()));
+            }
+            QSqlQuery query = this->queryInterpreter->build(q);
+            this->db->select(query);
+            auto maps = this->convertQueryResult(query);
+            auto converted = this->convert(maps, EntityHelper::getClassname(ptr.data()));
+            return this->convertList<T>(converted);
+        }
+        return QList<QSharedPointer<T>>();
+    }
+
+
     template<class T> QList<QSharedPointer<T>> findAll() {
         QSharedPointer<Entity> ptr = QSharedPointer<Entity>
                                      (EntityInstanceFactory::createInstance<T *>());
diff --git a/src/expression.cpp b/src/expression.cpp
index 2b02f6d..82ddc17 100644
--- a/src/expression.cpp
+++ b/src/expression.cpp
@@ -35,7 +35,7 @@ void Expression::setOnlyColumn(bool value) {
     onlyColumn = value;
 }
 
-void Expression::addParam(const QString &key, const QVariant &value) {
+void Expression::appendParam(const QString &key, const QVariant &value) {
     this->params.insert(key, value);
 }
 
diff --git a/src/expression.h b/src/expression.h
index 6d487f5..c35753b 100644
--- a/src/expression.h
+++ b/src/expression.h
@@ -34,7 +34,7 @@ class Expression {
     bool getOnlyColumn() const;
     void setOnlyColumn(bool value);
 
-    void addParam(const QString &key, const QVariant &value);
+    void appendParam(const QString &key, const QVariant &value);
     QHash<QString, QVariant> getParams() const;
     void setParams(const QHash<QString, QVariant> &value);
 
diff --git a/src/query.cpp b/src/query.cpp
index 0670ad7..550fa4a 100644
--- a/src/query.cpp
+++ b/src/query.cpp
@@ -16,6 +16,7 @@
 
 #include "query.h"
 #include "orderby.h"
+#include <QDebug>
 using namespace CuteEntityManager;
 Query::Query() {
     //this->select << Expression("*");
diff --git a/src/querybuilder.cpp b/src/querybuilder.cpp
index b5453f0..d108ada 100644
--- a/src/querybuilder.cpp
+++ b/src/querybuilder.cpp
@@ -860,7 +860,7 @@ Expression QueryBuilder::inFunction(QString column,
             }
             QString paramName = column + "_in" + var;
             condition += this->placeHolder(paramName);
-            exp.addParam(paramName, values.at(var));
+            exp.appendParam(paramName, values.at(var));
         }
         condition += ")";
     }
@@ -913,13 +913,16 @@ void QueryBuilder::setSeparator(const QString &value) {
 }
 
 
-QString QueryBuilder::limit(const quint64 &limit, const quint64 &offset) const {
+QString QueryBuilder::limit(const quint64 &limit, const quint64 &offset,
+                            bool withSpace) const {
     QString s = "";
     if (limit > 0) {
-        s.append(" " + this->limitKeyword() + " ").append(QString::number(limit));
+        s.append((withSpace ? " " : "") + this->limitKeyword() + " ").append(
+            QString::number(limit));
     }
     if (offset > 0) {
-        s.append(" " + this->offsetKeyword() + " ").append(QString::number(offset));
+        s.append((withSpace ? " " : "") + this->offsetKeyword() + " ").append(
+            QString::number(offset));
     }
     return s;
 }
@@ -1178,7 +1181,7 @@ Expression QueryBuilder::andOperator(QHash<QString, QVariant> conditions) {
         }
         condition += this->schema->quoteColumnName(var.key()) + " = " +
                      this->placeHolder(var.key());
-        exp.addParam(var.key(), var.value());
+        exp.appendParam(var.key(), var.value());
     }
     exp.setExpression(condition);
     return exp;
@@ -1189,9 +1192,8 @@ Expression QueryBuilder::arbitraryOperator(QString op, QString column,
     Expression exp = Expression(this->schema->quoteColumnName(
                                     column) + " " + op + " " +
                                 this->placeHolder(column));
-    exp.addParam(column, value);
+    exp.appendParam(column, value);
     return exp;
-
 }
 
 Expression QueryBuilder::isNull(QString column) {
@@ -1221,8 +1223,8 @@ Expression QueryBuilder::plainNand() {
 
 Expression QueryBuilder::like(QString column, QVariant value,
                               JokerPosition jp, QChar wildcard) {
-    return Expression(this->arbitraryOperator(this->likeKeyword(), column,
-                      this->addWildcard(value, jp, wildcard)));
+    return this->arbitraryOperator(this->likeKeyword(), column,
+                      this->addWildcard(value, jp, wildcard));
 }
 
 Expression QueryBuilder::like(QHash<QString, QVariant> conditions,
@@ -1242,7 +1244,7 @@ Expression QueryBuilder::like(QHash<QString, QVariant> conditions,
                          + " " +
                          this->placeHolder(i.key());
             QString newVal = this->addWildcard(i.value(), jp, wildcard);
-            exp.addParam(i.key(), newVal.isEmpty() ? i.value() : newVal);
+            exp.appendParam(i.key(), newVal.isEmpty() ? i.value() : newVal);
         }
         condition += ")";
         exp.setExpression(condition);
@@ -1254,7 +1256,7 @@ Expression QueryBuilder::where(QString column, QVariant value) {
     QString placeholder = column + "_where";
     Expression exp = Expression(this->schema->quoteColumnName(column) + "=" +
                                 this->placeHolder(placeholder));
-    exp.addParam(placeholder, value);
+    exp.appendParam(placeholder, value);
     return exp;
 }
 
@@ -1263,7 +1265,7 @@ Expression QueryBuilder::where(QHash<QString, QVariant> conditions,
     Expression exp = Expression(this->where(conditions, conjunction, false, "id",
                                             false));
     for (auto i = conditions.constBegin(); i != conditions.constEnd(); ++i) {
-        exp.addParam(i.key(), i.value());
+        exp.appendParam(i.key(), i.value());
     }
     return exp;
 }
@@ -1272,7 +1274,7 @@ Expression QueryBuilder::where(QString condition,
                                QHash<QString, QVariant> values) {
     Expression exp = Expression(condition);
     for (auto i = values.constBegin(); i != values.constEnd(); ++i) {
-        exp.addParam(i.key(), i.value());
+        exp.appendParam(i.key(), i.value());
     }
     return exp;
 }
@@ -1297,8 +1299,8 @@ Expression QueryBuilder::notBetween(QString column, QVariant firstValue,
 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);
+    exp.appendParam(ph1, val1);
+    exp.appendParam(ph2, val2);
     return exp;
 }
 
@@ -1325,7 +1327,7 @@ Expression QueryBuilder::orOperator(
             condition += this->schema->quoteColumnName(i.key()) + (like ? " " +
                          this->likeKeyword() + " " : "=") +
                          this->placeHolder(i.key());
-            exp.addParam(i.key(), i.value());
+            exp.appendParam(i.key(), i.value());
         }
         condition += ")";
         exp.setExpression(condition);
diff --git a/src/querybuilder.h b/src/querybuilder.h
index 9051e12..c001cb4 100644
--- a/src/querybuilder.h
+++ b/src/querybuilder.h
@@ -220,7 +220,7 @@ class QueryBuilder {
                      const QString &primaryKey = "id") const;
     QList<QSqlQuery> createOrMerge(const QSharedPointer<Entity> &entity,
                                    bool insert) const;
-    virtual QString limit(const quint64 &limit, const quint64 &offset) const;
+    virtual QString limit(const quint64 &limit, const quint64 &offset, bool withSpace=true) const;
     QString generateIndexName(const QString &name, const QString &table,
                               const QString &refColumn, const QString &refTable, const bool fk) const;
     QString generateColumnNameID(QString name) const;
diff --git a/src/queryinterpreter.cpp b/src/queryinterpreter.cpp
index 1a6b3d2..f944ec7 100644
--- a/src/queryinterpreter.cpp
+++ b/src/queryinterpreter.cpp
@@ -21,6 +21,7 @@
 #include "orderby.h"
 #include "expression.h"
 #include "schema.h"
+#include <QDebug>
 using namespace CuteEntityManager;
 
 
@@ -28,15 +29,15 @@ QueryInterpreter::QueryInterpreter(QSharedPointer<QueryBuilder> builder) {
     this->builder = builder;
 }
 
-QSqlQuery QueryInterpreter::build(const Query &q) {
+QSqlQuery QueryInterpreter::build(Query &q) {
     QList<QString> clauses = QList<QString>();
-    clauses.append(this->buildSelect(q.getSelect(), q.getDistinct(),
+    clauses.append(this->buildSelect(q, q.getSelect(), q.getDistinct(),
                                      q.getSelectOption()));
     clauses.append(this->buildFrom(q.getFrom()));
     clauses.append(this->buildJoin(q.getJoins()));
-    clauses.append(this->buildWhere(q.getWhere()));
+    clauses.append(this->buildWhere(q, q.getWhere()));
     clauses.append(this->buildGroupBy(q.getGroupBy()));
-    clauses.append(this->buildHaving(q.getHaving()));
+    clauses.append(this->buildHaving(q, q.getHaving()));
     QString sql = "";
     bool first = true;
     for (int i = 0; i < clauses.size(); ++i) {
@@ -54,11 +55,19 @@ QSqlQuery QueryInterpreter::build(const Query &q) {
                                      q.getOffset());
     QSqlQuery sqlQuery = this->builder->getQuery();
     sqlQuery.prepare(sql);
+    qDebug() << "--------------------------------------";
+    for (auto i = q.getParams().constBegin(); i != q.getParams().constEnd(); ++i) {
+        qDebug() << i.key() << i.value();
+    }
+    qDebug() << "--------------------------------------";
+
+
     this->builder->bindValues(q.getParams(), sqlQuery, false);
     return sqlQuery;
 }
 
-QString QueryInterpreter::buildSelect(const QList<Expression> &columns,
+QString QueryInterpreter::buildSelect(Query &q,
+                                      const QList<Expression> &columns,
                                       const bool &distinct, const QString &selectOption) const {
     QString sqlSelect = distinct ? "SELECT DISTINCT" : "SELECT";
     if (!selectOption.isEmpty()) {
@@ -75,6 +84,7 @@ QString QueryInterpreter::buildSelect(const QList<Expression> &columns,
             sqlSelect += ", ";
         }
         Expression e = columns.at(i);
+        q.appendParams(e.getParams());
         QString nExp = e.getExpression();
         if (e.getOnlyColumn()) {
             sqlSelect += this->builder->getSchema()->quoteColumnName(e.getExpression());
@@ -139,9 +149,10 @@ QString QueryInterpreter::buildJoin(const QList<Join> &joins) const {
     return sqlJoin;
 }
 
-QString QueryInterpreter::buildWhere(const QList<Expression> &conditions)
+QString QueryInterpreter::buildWhere(Query &q,
+                                     const QList<Expression> &conditions)
 const {
-    QString where = this->buildCondition(conditions);
+    QString where = this->buildCondition(q, conditions);
     return where.isEmpty() ? "" : ("WHERE " + where);
 }
 
@@ -150,9 +161,10 @@ QString QueryInterpreter::buildGroupBy(const QStringList &groupBy) const {
                groupBy);
 }
 
-QString QueryInterpreter::buildHaving(const QList<Expression> &conditions)
+QString QueryInterpreter::buildHaving(Query &q,
+                                      const QList<Expression> &conditions)
 const {
-    QString having = this->buildCondition(conditions);
+    QString having = this->buildCondition(q, conditions);
     return having.isEmpty() ? "" : ("HAVING " + having);
 }
 
@@ -163,7 +175,7 @@ QString QueryInterpreter::buildOrderByAndLimit(QString sql,
     if (!sqlOrderBy.isEmpty()) {
         sql += this->builder->getSeparator() + sqlOrderBy;
     }
-    QString sqlLimit = this->builder->limit(limit, offset);
+    QString sqlLimit = this->builder->limit(limit, offset, false);
     if (!sqlLimit.isEmpty()) {
         sql += this->builder->getSeparator() + sqlLimit;
     }
@@ -202,7 +214,8 @@ QString QueryInterpreter::buildOrderBy(const QList<OrderBy> &columns) const {
     return sqlOrder;
 }
 
-QString QueryInterpreter::buildCondition(const QList<Expression> &conditions)
+QString QueryInterpreter::buildCondition(Query &q,
+        const QList<Expression> &conditions)
 const {
     if (conditions.isEmpty()) {
         return "";
@@ -220,6 +233,7 @@ const {
             }
         }
         sqlCondition += expression;
+        q.appendParams(q.getParams());
     }
     return sqlCondition;
 }
diff --git a/src/queryinterpreter.h b/src/queryinterpreter.h
index a5ec087..b767781 100644
--- a/src/queryinterpreter.h
+++ b/src/queryinterpreter.h
@@ -28,21 +28,21 @@ class Expression;
 class QueryInterpreter {
   public:
     QueryInterpreter(QSharedPointer<QueryBuilder> builder);
-    QSqlQuery build(const Query &q);
+    QSqlQuery build(Query &q);
 
   protected:
-    QString buildSelect(const QList<Expression> &columns,
+    QString buildSelect(Query &q, 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<Expression> &conditions) const;
+    QString buildWhere(Query &q, const QList<Expression> &conditions) const;
     QString buildGroupBy(const QStringList &groupBy) const;
-    QString buildHaving(const QList<Expression> &conditions) const;
+    QString buildHaving(Query &q, 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<Expression> &conditions) const;
+    QString buildCondition(Query &q, const QList<Expression> &conditions) const;
 
   private:
     QSharedPointer<QueryBuilder> builder;
