commit dbd41a3a0674608cf6da011a58efb8a53f06a2f0
Author: Christian Ehringfeld <c.ehringfeld@t-online.de>
Date:   Sun Jan 10 22:14:45 2016 +0100

    ...

diff --git a/.travis.yml b/.travis.yml
index 9aeb84d..c233225 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,23 +9,10 @@ env:
   - CONFIG=Debug
 
 install:
-  - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then
-      sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
-      && sudo apt-add-repository -y ppa:beineri/opt-qt541
-      && sudo apt-get -qq update
-      && sudo apt-get -qq install gcc-5 libc6-i386 qt54tools qt54svg qt54webkit
-      && export CXX="g++-5"
-      && export CC="gcc-5"
-      && export QMAKE=/usr/lib/x86_64-linux-gnu/qt5/bin/qmake
-      ;
-    else
-         brew update
-      && brew unlink cmake
-      && brew install cmake
-      && brew install qt5
-      && chmod -R 755 /usr/local/opt/qt5/*
-      ;
-    fi
+    - sudo add-apt-repository -y ppa:ubuntu-sdk-team/ppa &&
+    sudo apt-get update &&
+    sudo apt-get install qtbase5-dev libqt5sql5-mysql libqt5sql5-sqlite &&
+    sudo apt-get install lcov odbcinst libmyodbc odbc-postgresql
 
 script:
   -  QMAKE
diff --git a/appveyor.yml b/appveyor.yml
index f1f92bc..6a7eba2 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -2,15 +2,18 @@
 # http://www.appveyor.com/docs/build-configuration
 os: unstable
 
+configuration:
+  - debug
+  - release
+
 install:
-  - set QTDIR=C:\Qt\5.4\mingw491_32
+  - set QTDIR=C:\Qt\5.5\mingw482_32
   - set PATH=%PATH%;%QTDIR%\bin;C:\MinGW\bin
     #  - set RELEASE_PATH=appveyor\release
 
 build_script:
   # using a header file without MemoryBarrier, that causes the build to fail
   - qmake EntityManager.pro
-#  - qmake QOwnNotes.pro -r -spec win32-g++ "CONFIG+=debug"
   - mingw32-make -j8
   # creating the release path
   #  - md ..\%RELEASE_PATH%
diff --git a/src/attributeresolver.cpp b/src/attributeresolver.cpp
new file mode 100644
index 0000000..9ea3c7b
--- /dev/null
+++ b/src/attributeresolver.cpp
@@ -0,0 +1,177 @@
+#include "attributeresolver.h"
+#include "entityhelper.h"
+#include "querybuilder.h"
+#include <QDebug>
+using namespace CuteEntityManager;
+
+AttributeResolver::AttributeResolver(QSharedPointer<QueryBuilder> queryBuilder) {
+    this->qb = queryBuilder;
+}
+
+AttributeResolver::~AttributeResolver() {
+    this->qb = QSharedPointer<QueryBuilder>(nullptr);
+    if(!this->attributes.isEmpty()) {
+        QMutableHashIterator<QString, QHash<QString, Attribute*>> i(this->attributes);
+        while(i.hasNext()) {
+            i.next();
+            auto embeddedHash = i.value();
+            QMutableHashIterator<QString, Attribute*> i2(embeddedHash);
+            while(i2.hasNext()) {
+                i2.next();
+                auto attr = i2.value();
+                delete attr;
+                i2.remove();
+            }
+            i.remove();
+        }
+    }
+}
+
+QHash<QString, QHash<QString, Attribute *>> AttributeResolver::getAttributes() const {
+    return attributes;
+}
+
+void AttributeResolver::setAttributes(const QHash<QString, QHash<QString, Attribute*>>
+                                      &value) {
+    attributes = value;
+}
+
+Attribute *AttributeResolver::resolveManyToManyAttribute(const QSharedPointer<Entity> &e,
+        const QString &attr, const Relation &r, const QSharedPointer<Entity> &target) {
+    auto ptr = e;
+    QString attributeName = r.getPropertyName();
+    QString foreignColumnName = target->getTablename();
+    auto baseObj = EntityHelper::getBaseClassObject(e, attributeName);
+    Entity* foreignBaseObj = target.data();
+    if (!r.getMappedBy().isEmpty()) {
+        ptr = target;
+        attributeName = r.getMappedBy();
+        foreignBaseObj = EntityHelper::getBaseClassObject(ptr, attributeName);
+        foreignColumnName = foreignBaseObj->getTablename();
+    }
+    Attribute *attrObj = new Attribute(attr,
+                                       this->qb->generateColumnNameID(baseObj->getTablename()),
+                                       baseObj->getTablename(), e->metaObject());
+    this->resolveInheritance(e, attrObj);
+    attrObj->setRelation(foreignBaseObj->getTablename(), target->metaObject(), r,
+                         this->qb->generateManyToManyTableName((r.getMappedBy().isEmpty() ? baseObj->getTablename()
+                                 : foreignBaseObj->getTablename()), attributeName),
+                         this->qb->generateColumnNameID(foreignColumnName));
+    delete baseObj;
+    if(foreignBaseObj != target.data()) {
+        delete foreignBaseObj;
+    }
+    return attrObj;
+}
+
+Attribute *AttributeResolver::resolveManyToOneAttribute(const QSharedPointer<Entity> &e,
+        const QString &attr, const Relation &r, const QSharedPointer<Entity> &target) {
+    Q_UNUSED(r);
+    auto obj = EntityHelper::getBaseClassObject(e, attr);
+    Attribute *attrObj = new Attribute(attr,
+                                       this->qb->generateColumnNameID(attr),
+                                       e->getTablename(), e->metaObject());
+    this->resolveInheritance(e, attrObj);
+    attrObj->setRelation(target->getTablename(), target->metaObject(), r, "", "id");
+    delete obj;
+    return attrObj;
+}
+
+Attribute *AttributeResolver::resolveOneToManyAttribute(const QSharedPointer<Entity> &e,
+        const QString &attr, const Relation &r, const QSharedPointer<Entity> &target) {
+    auto obj = EntityHelper::getBaseClassObject(e, attr);
+    Attribute *attrObj = new Attribute(attr, "id",
+                                       e->getTablename(), e->metaObject());
+    this->resolveInheritance(e, attrObj);
+    attrObj->setRelation(target->getTablename(), target->metaObject(), r, "",
+                         this->qb->generateColumnNameID(r.getMappedBy()));
+    delete obj;
+    return attrObj;
+}
+
+Attribute *AttributeResolver::resolveNonRelatedAttribute(const QSharedPointer<Entity> &e,
+        const QString &attr) {
+    Attribute *obj = new Attribute(attr, attr, e->getTablename(), e->metaObject());
+    this->resolveInheritance(e, obj);
+    return obj;
+}
+
+const QMetaObject *AttributeResolver::resolveInheritance(const QSharedPointer<Entity> &e,
+        Attribute *&attribute) {
+    auto obj = EntityHelper::getBaseClassObject(e, attribute->getName());
+    if(obj && obj->getTablename() != e->getTablename()) {
+        attribute->setInheritance(obj->getTablename(), obj->metaObject());
+    }
+    return obj->metaObject();
+}
+
+void AttributeResolver::addAttribute(const QString &className, Attribute *&attr) {
+    auto attrs = this->attributes.value(className);
+    attrs.insert(attr->getName(), attr);
+    this->attributes.insert(className, attrs);
+}
+
+Attribute *AttributeResolver::resolveExplicitAttribute(const QSharedPointer<Entity>
+        &classObj, const QString &attribute, QSharedPointer<Entity> related) {
+    Attribute* a = nullptr;
+    if(classObj->getRelations().contains(attribute)) {
+        auto relation = classObj->getRelations().value(attribute);
+        if(relation.getType() == RelationType::MANY_TO_MANY) {
+            a = this->resolveManyToManyAttribute(classObj, attribute, relation, related);
+        } else if(relation.getType() == RelationType::MANY_TO_ONE ||
+                  (relation.getType() == RelationType::ONE_TO_ONE && relation.getMappedBy().isEmpty())) {
+            a = this->resolveManyToOneAttribute(classObj, attribute, relation, related);
+        } else {
+            a = this->resolveOneToManyAttribute(classObj, attribute, relation, related);
+        }
+    } else {
+        a = this->resolveNonRelatedAttribute(classObj, attribute);
+    }
+    return a;
+}
+
+QSharedPointer<QueryBuilder> AttributeResolver::getQb() const {
+    return qb;
+}
+
+bool AttributeResolver::containsAttribute(const QString &className,
+        const QString &attribute) const {
+    bool r = false;
+    auto attributes = this->getAttributes();
+    if(!this->attributes.isEmpty() && attributes.contains(className) &&
+            !attributes.value(className).isEmpty() &&
+            attributes.value(className).contains(attribute)) {
+        r = true;
+    }
+    return r;
+}
+
+Attribute *AttributeResolver::resolveAttribute(const QSharedPointer<Entity> &classObj,
+        const QString &attribute, QSharedPointer<Entity> related) {
+    Attribute *attr = nullptr;
+    if(this->containsAttribute(classObj->getClassname(), attribute)) {
+        attr = this->attributes.value(classObj->getClassname()).value(attribute);
+    } else {
+        attr = this->resolveExplicitAttribute(classObj, attribute, related);
+        this->addAttribute(classObj->getClassname(), attr);
+    }
+    return attr;
+}
+
+Attribute *AttributeResolver::resolveAttribute(const QString &className,
+        const QString &attribute, const QString related) {
+    Attribute *attr = nullptr;
+    if(!className.isEmpty()) {
+        if(this->containsAttribute(className, attribute)) {
+            attr = this->attributes.value(className).value(attribute);
+        } else {
+            QSharedPointer<Entity> e = QSharedPointer<Entity>(EntityInstanceFactory::createInstance(
+                                           className));
+            QSharedPointer<Entity> rel = QSharedPointer<Entity>(EntityInstanceFactory::createInstance(
+                                             related));
+            attr = this->resolveExplicitAttribute(e, attribute, rel);
+            this->addAttribute(className, attr);
+        }
+    }
+    return attr;
+}
diff --git a/src/attributeresolver.h b/src/attributeresolver.h
new file mode 100644
index 0000000..0b06228
--- /dev/null
+++ b/src/attributeresolver.h
@@ -0,0 +1,43 @@
+#ifndef ATTRIBUTERESOLVER_H
+#define ATTRIBUTERESOLVER_H
+#include <QHash>
+#include <QString>
+#include "attribute.h"
+#include "entity.h"
+namespace CuteEntityManager {
+class QueryBuilder;
+class AttributeResolver {
+  public:
+    AttributeResolver(QSharedPointer<QueryBuilder> queryBuilder);
+    virtual ~AttributeResolver();
+    bool containsAttribute(const QString &className, const QString &attribute) const;
+    Attribute* resolveAttribute(const QSharedPointer<Entity> &classObj,
+                                const QString &attribute, QSharedPointer<Entity> related = QSharedPointer<Entity>());
+    Attribute* resolveAttribute(const QString &className, const QString &attribute,
+                                const QString related = "");
+    QHash<QString, QHash<QString, Attribute *>> getAttributes() const;
+    void setAttributes(const QHash<QString, QHash<QString, Attribute *>> &value);
+    QSharedPointer<QueryBuilder> getQb() const;
+
+  protected:
+    Attribute* resolveManyToManyAttribute(const QSharedPointer<Entity> &e,
+                                          const QString &attr, const Relation &r, const QSharedPointer<Entity> &target);
+    Attribute* resolveManyToOneAttribute(const QSharedPointer<Entity> &e, const QString &attr,
+                                         const Relation &r, const QSharedPointer<Entity> &target);
+    Attribute* resolveOneToManyAttribute(const QSharedPointer<Entity> &e, const QString &attr,
+                                         const Relation &r, const QSharedPointer<Entity> &target);
+    Attribute* resolveNonRelatedAttribute(const QSharedPointer<Entity> &e,
+                                          const QString &attr);
+    const QMetaObject *resolveInheritance(const QSharedPointer<Entity> &e,
+                                          Attribute *&attribute);
+    void addAttribute(const QString &className, Attribute *&attr);
+    Attribute* resolveExplicitAttribute(const QSharedPointer<Entity> &classObj,
+                                        const QString &attribute, QSharedPointer<Entity> related = QSharedPointer<Entity>());
+
+  private:
+    QSharedPointer<QueryBuilder> qb;
+    QHash<QString, QHash<QString, Attribute*>> attributes;
+};
+}
+
+#endif // ATTRIBUTERESOLVER_H
diff --git a/src/entitymanager.cpp b/src/entitymanager.cpp
index 4017784..4f3bc66 100644
--- a/src/entitymanager.cpp
+++ b/src/entitymanager.cpp
@@ -48,8 +48,15 @@ void EntityManager::init(bool inspect, const MsgType msgType) {
     this->schema = QSharedPointer<Schema>(Database::getSchema(Database::getDatabaseType(
             this->db->getDatabase().driverName()), this->db));
     this->schema->setTables(this->schema->getTableSchemas());
+<<<<<<< Updated upstream
     this->queryInterpreter = QSharedPointer<QueryInterpreter>(new QueryInterpreter(
                                  this->schema->getQueryBuilder().data()));
+=======
+    this->ar = QSharedPointer<AttributeResolver>(new AttributeResolver(
+                   this->schema->getQueryBuilder()));
+    this->queryInterpreter = QSharedPointer<QueryInterpreter>(new QueryInterpreter(
+                                 this->ar));
+>>>>>>> Stashed changes
     this->appendToInstanceList();
     if (inspect) {
         EntityInspector inspector = EntityInspector(msgType);
diff --git a/src/entitymanager.h b/src/entitymanager.h
index ce7ac75..36e3dc2 100644
--- a/src/entitymanager.h
+++ b/src/entitymanager.h
@@ -170,7 +170,7 @@ class EntityManager : public QObject {
             if (joinBaseClasses) {
                 q.appendJoins(this->schema->getQueryBuilder()->joinBaseClasses(ptr));
             }
-            QSqlQuery query = this->queryInterpreter->build(q);
+            QSqlQuery query = this->queryInterpreter->build(q,ptr->metaObject());
             auto maps = this->convertQueryResult(query);
             auto converted = this->convert(maps, EntityHelper::getClassname(ptr.data()),
                                            false,
diff --git a/src/query.cpp b/src/query.cpp
index b2aa54d..2c9780a 100644
--- a/src/query.cpp
+++ b/src/query.cpp
@@ -17,6 +17,7 @@
 #include "query.h"
 #include "entity.h"
 #include "querybuilder.h"
+#include "entityinstancefactory.h"
 using namespace CuteEntityManager;
 Query::Query() {
 }
@@ -213,6 +214,16 @@ Expression Query::like(const QSharedPointer<QueryBuilder> &qb,
     return qb->like(conditions, conjunction, jp, wildcard);
 }
 
+QVariant Query::convertParam(QVariant &val) {
+    if(QString(val.typeName()).contains("QSharedPointer")) {
+        auto entity = EntityInstanceFactory::castQVariant(val);
+        if(entity && entity->getId() != -1) {
+            return entity->getProperty(entity->getPrimaryKey());
+        }
+    }
+    return val;
+}
+
 QString Query::getSelectOption() const {
     return selectOption;
 }
diff --git a/src/query.h b/src/query.h
index 5c92388..7499bfc 100644
--- a/src/query.h
+++ b/src/query.h
@@ -43,7 +43,7 @@ enum class Direction;
 class Query {
   public:
     Query();
-    ~Query();
+    virtual ~Query();
     explicit Query(QStringList from, QList<Expression> where = QList<Expression>(),
                    QList<Join> joins = QList<Join>(),
                    QHash<QString, QVariant> params = QHash<QString, QVariant>(), quint64 limit = 0,
@@ -165,6 +165,8 @@ class Query {
                     QHash<QString, QVariant> conditions,
                     QString conjunction = QStringLiteral("AND"),
                     JokerPosition jp = JokerPosition::BOTH, QChar wildcard = '%');
+protected:
+    QVariant convertParam(QVariant &val);
 
   private:
     QList<Expression> select;
diff --git a/src/querybuilder.cpp b/src/querybuilder.cpp
index 5fb8634..5839d6c 100644
--- a/src/querybuilder.cpp
+++ b/src/querybuilder.cpp
@@ -13,11 +13,12 @@
  * 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 <QMetaObject>
+#include <QRegularExpression>
+#include <QStringList>
 #include "querybuilder.h"
 #include "database.h"
-#include <QMetaObject>
 #include "entity.h"
-#include <QRegularExpression>
 #include "entityinstancefactory.h"
 #include "entityhelper.h"
 #include "logger.h"
@@ -1093,7 +1094,9 @@ void QueryBuilder::bindValue(const QString &key, const QVariant &value,
 }
 
 QString QueryBuilder::placeHolder(const QString &key) const {
-    return QString(":" + key);
+    QString nKey = key;
+    nKey.replace(".","_");
+    return QString(":" + nKey);
 }
 
 QString QueryBuilder::where(const QHash<QString, QVariant> &m,
diff --git a/src/queryinterpreter.cpp b/src/queryinterpreter.cpp
index ed70706..f76c1b0 100644
--- a/src/queryinterpreter.cpp
+++ b/src/queryinterpreter.cpp
@@ -17,18 +17,18 @@
 #include "queryinterpreter.h"
 #include "join.h"
 #include "query.h"
-#include "querybuilder.h"
+#include "attributeresolver.h"
 #include "orderby.h"
 #include "expression.h"
 #include "schema.h"
 using namespace CuteEntityManager;
 
 
-QueryInterpreter::QueryInterpreter(QueryBuilder *builder) {
-    this->builder = builder;
+QueryInterpreter::QueryInterpreter(QSharedPointer<AttributeResolver> ar) {
+    this->ar = ar;
 }
 
-QSqlQuery QueryInterpreter::build(Query &q) {
+QSqlQuery QueryInterpreter::build(Query &q, const QMetaObject *obj) {
     QList<QString> clauses = QList<QString>();
     clauses.append(this->buildSelect(q, q.getSelect(), q.getDistinct(),
                                      q.getSelectOption()));
@@ -45,23 +45,23 @@ QSqlQuery QueryInterpreter::build(Query &q) {
             if (first) {
                 first = false;
             } else {
-                sql += this->builder->getSeparator();
+                sql += this->ar->getQb()->getSeparator();
             }
             sql += clause;
         }
     }
     sql = this->buildOrderByAndLimit(sql, q.getOrderBy(), q.getLimit(),
                                      q.getOffset());
-    QSqlQuery sqlQuery = this->builder->getQuery();
+    QSqlQuery sqlQuery = this->ar->getQb()->getQuery();
     sqlQuery.prepare(sql);
-    this->builder->bindValues(q.getParams(), sqlQuery, false);
+    this->ar->getQb()->bindValues(q.getParams(), sqlQuery, false);
     return sqlQuery;
 }
 
 QString QueryInterpreter::buildSelect(Query &q,
                                       const QList<Expression> &columns,
                                       const bool &distinct, const QString &selectOption) const {
-    QString sqlSelect = distinct ? ("SELECT " + this->builder->distinct() + " ") :
+    QString sqlSelect = distinct ? ("SELECT " + this->ar->getQb()->distinct() + " ") :
                         "SELECT ";
     if (!selectOption.isEmpty()) {
         sqlSelect += selectOption + " ";
@@ -80,7 +80,7 @@ QString QueryInterpreter::buildSelect(Query &q,
         q.appendParams(e.getParams());
         QString nExp = e.getExpression();
         if (e.getOnlyColumn()) {
-            sqlSelect += this->builder->getSchema()->quoteColumnName(e.getExpression());
+            sqlSelect += this->ar->getQb()->getSchema()->quoteColumnName(e.getExpression());
         } else if (!nExp.contains("(")) {
             QRegularExpression re =
                 QRegularExpression(
@@ -92,16 +92,16 @@ QString QueryInterpreter::buildSelect(Query &q,
                 for (int var = 0; var < 2; ++var) {
                     QRegularExpressionMatch match = iterator.next();
                     if (var == 1) {
-                        sqlSelect += this->builder->getSchema()->quoteColumnName(
-                                         match.captured()) + " AS " + this->builder->getSchema()->quoteColumnName("a" +
+                        sqlSelect += this->ar->getQb()->getSchema()->quoteColumnName(
+                                         match.captured()) + " AS " + this->ar->getQb()->getSchema()->quoteColumnName("a" +
                                                  QString::number(i));
                     }
                 }
             } else {
-                nExp = this->builder->getSchema()->quoteColumnName(nExp);
+                nExp = this->ar->getQb()->getSchema()->quoteColumnName(nExp);
             }
         } else {
-            sqlSelect += nExp + " AS " + this->builder->getSchema()->quoteColumnName("a" +
+            sqlSelect += nExp + " AS " + this->ar->getQb()->getSchema()->quoteColumnName("a" +
                          QString::number(i));
         }
     }
@@ -112,7 +112,7 @@ QString QueryInterpreter::buildFrom(const QStringList &from) const {
     if (from.isEmpty()) {
         return "";
     }
-    auto tables = this->builder->quoteTableNames(from);
+    auto tables = this->ar->getQb()->quoteTableNames(from);
     QString clause = "FROM ";
     bool first = true;
     for (int var = 0; var < tables.size(); ++var) {
@@ -133,18 +133,18 @@ QString QueryInterpreter::buildJoin(const QList<Join> &joins) const {
     QString sqlJoin = "";
     for (int i = 0; i < joins.size(); ++i) {
         Join j = joins.at(i);
-        sqlJoin += j.getType() + this->builder->getSeparator() +
-                   this->builder->getSchema()->quoteTableName(j.getForeignTable());
+        sqlJoin += j.getType() + this->ar->getQb()->getSeparator() +
+                   this->ar->getQb()->getSchema()->quoteTableName(j.getForeignTable());
         if (!j.getExpression().getExpression().isEmpty()) {
             QString expression = j.getExpression().getExpression();
             int count = expression.count("=");
             if (count < 1) {
-                expression = this->builder->getSchema()->quoteTableName(expression);
+                expression = this->ar->getQb()->getSchema()->quoteTableName(expression);
             } else if (count == 1) {
                 QStringList list = expression.split("=");
-                expression = this->builder->getSchema()->quoteColumnName(list.at(
+                expression = this->ar->getQb()->getSchema()->quoteColumnName(list.at(
                                  0).trimmed()) + " = ";
-                expression += this->builder->getSchema()->quoteColumnName(list.at(1).trimmed());
+                expression += this->ar->getQb()->getSchema()->quoteColumnName(list.at(1).trimmed());
             }
             sqlJoin += " ON " + expression;
         }
@@ -160,7 +160,7 @@ const {
 }
 
 QString QueryInterpreter::buildGroupBy(const QStringList &groupBy) const {
-    return groupBy.isEmpty() ? "" : "GROUP BY " + this->builder->buildColumns(
+    return groupBy.isEmpty() ? "" : "GROUP BY " + this->ar->getQb()->buildColumns(
                groupBy);
 }
 
@@ -175,11 +175,11 @@ QString QueryInterpreter::buildOrderByAndLimit(QString sql,
         const quint64 &offset) const {
     QString sqlOrderBy = this->buildOrderBy(orderBy);
     if (!sqlOrderBy.isEmpty()) {
-        sql += this->builder->getSeparator() + sqlOrderBy;
+        sql += this->ar->getQb()->getSeparator() + sqlOrderBy;
     }
-    QString sqlLimit = this->builder->limit(limit, offset, false);
+    QString sqlLimit = this->ar->getQb()->limit(limit, offset, false);
     if (!sqlLimit.isEmpty()) {
-        sql += this->builder->getSeparator() + sqlLimit;
+        sql += this->ar->getQb()->getSeparator() + sqlLimit;
     }
     return sql;
 }
@@ -200,7 +200,7 @@ QString QueryInterpreter::buildOrderBy(const QList<OrderBy> &columns) const {
         if (order.getColumn().isEmpty()) {
             sqlOrder += order.getExpressedDirection().getExpression();
         } else {
-            sqlOrder += this->builder->getSchema()->quoteColumnName(order.getColumn());
+            sqlOrder += this->ar->getQb()->getSchema()->quoteColumnName(order.getColumn());
             switch (order.getDirection()) {
             case Direction::SORT_ASC:
                 sqlOrder += " ASC";
@@ -230,7 +230,7 @@ QString QueryInterpreter::buildCondition(Query &q,
             if (first) {
                 first = false;
             } else if (expression.at(0) != ' ') {
-                sqlCondition += this->builder->getSeparator();
+                sqlCondition += this->ar->getQb()->getSeparator();
             }
         }
         sqlCondition += expression;
diff --git a/src/queryinterpreter.h b/src/queryinterpreter.h
index b1d7632..aa7de4c 100644
--- a/src/queryinterpreter.h
+++ b/src/queryinterpreter.h
@@ -21,14 +21,14 @@
 #include <QRegularExpressionMatchIterator>
 namespace CuteEntityManager {
 class Query;
-class QueryBuilder;
 class Join;
 class OrderBy;
 class Expression;
+class AttributeResolver;
 class QueryInterpreter {
   public:
-    QueryInterpreter(QueryBuilder *builder);
-    QSqlQuery build(Query &q);
+    QueryInterpreter(QSharedPointer<AttributeResolver> ar);
+    QSqlQuery build(Query &q, const QMetaObject *obj=nullptr);
 
   protected:
     QString buildSelect(Query &q, const QList<Expression> &columns,
@@ -45,7 +45,7 @@ class QueryInterpreter {
     QString buildCondition(Query &q, const QList<Expression> &conditions) const;
 
   private:
-    QueryBuilder *builder;
+    QSharedPointer<AttributeResolver> ar;
 
 };
 
