commit 87739ae02642e8137fcb166f4e9b97a52f6f451e
Author: Christian Ehringfeld <c.ehringfeld@t-online.de>
Date:   Sat Oct 10 01:50:57 2015 +0200

    some (performance) improvements

diff --git a/src/entityhelper.cpp b/src/entityhelper.cpp
index a70b290..c7d0db2 100644
--- a/src/entityhelper.cpp
+++ b/src/entityhelper.cpp
@@ -102,20 +102,43 @@ const QHash<QString, QMetaProperty> EntityHelper::getMetaProperties(
     return h;
 }
 
+const QHash<QString, QMetaProperty> EntityHelper::getNonInheritedMetaProperties(
+    const Entity *entity) {
+    auto props = EntityHelper::getMetaProperties(entity);
+    auto superObject = EntityInstanceFactory::newSuperClassInstance(entity);
+    if (superObject) {
+        auto superProps = EntityHelper::getMetaProperties(superObject);
+        for (auto iterator = superProps.constBegin(); iterator != superProps.constEnd();
+                ++iterator) {
+            if (props.contains(iterator.key())) {
+                props.remove(iterator.key());
+            }
+        }
+        delete superObject;
+        superObject = nullptr;
+    }
+    return props;
+}
+
 const QHash<QString, QMetaProperty> EntityHelper::getInheritedMetaProperties(
     const Entity *entity) {
-    auto classes = EntityHelper::superClasses(entity);
+    auto props = EntityHelper::getMetaProperties(entity);
+    auto superObject = EntityInstanceFactory::newSuperClassInstance(entity);
     auto wholeProperties = QHash<QString, QMetaProperty>();
-    for (int var = classes.size() - 1; var >= 0; --var) {
-        auto metaObject = classes.at(var);
-        auto properties = EntityHelper::getMetaProperties(metaObject);
-        auto iterator = properties.constBegin();
-        while (iterator != properties.constEnd()) {
-            wholeProperties.insert(iterator.key(), iterator.value());
-            ++iterator;
+    if (superObject) {
+        auto superProps = EntityHelper::getMetaProperties(superObject);
+        auto iterator = superProps.constBegin();
+        for (auto i = props.constBegin(); i != props.constEnd(); ++i) {
+            if (!superProps.contains(iterator.key())) {
+                wholeProperties.insert(iterator.key(), iterator.value());
+            }
         }
+        delete superObject;
+        superObject = nullptr;
     }
     return wholeProperties;
+
+
 }
 
 const QHash<Relation, QMetaProperty> EntityHelper::getRelationProperties(
diff --git a/src/entityhelper.h b/src/entityhelper.h
index 2ff9421..a86483d 100644
--- a/src/entityhelper.h
+++ b/src/entityhelper.h
@@ -37,6 +37,7 @@ class EntityHelper {
         const Entity *entity);
     static const QHash<QString, QMetaProperty> getMetaProperties(
         const QMetaObject *object);
+    static const QHash<QString, QMetaProperty> getNonInheritedMetaProperties(const Entity *entity);
     static const QHash<QString, QMetaProperty> getInheritedMetaProperties(
         const Entity *entity);
     static const QHash<Relation, QMetaProperty> getRelationProperties(
diff --git a/src/entitymanager.cpp b/src/entitymanager.cpp
index 5892c70..5f1a516 100644
--- a/src/entitymanager.cpp
+++ b/src/entitymanager.cpp
@@ -176,7 +176,7 @@ bool EntityManager::createObject(QSharedPointer<Entity> &entity,
                 this->cache.insert(entity);
                 if (persistRelations) {
                     this->savePostPersistedRelations(entity, mergedObjects,
-                                                     relationsIgnoreHasChanged);
+                                                     relationsIgnoreHasChanged, true);
                 }
                 rc = true;
             }
@@ -202,6 +202,24 @@ bool EntityManager::create(QSharedPointer<Entity> &entity,
                               checkDuplicate, validate, relationsIgnoreHasChanged);
 }
 
+bool EntityManager::create(QList<QSharedPointer<Entity> > entities,
+                           const bool persistRelations, const bool validate,
+                           const bool relationsIgnoreHasChanged, const bool checkDuplicate) {
+    bool ok = true;
+    auto merged = QList<Entity *>();
+    foreach (QSharedPointer<Entity> ent, entities) {
+        ok = this->createObject(ent, merged, persistRelations,
+                                checkDuplicate, validate, relationsIgnoreHasChanged);
+        if (!ok) {
+            break;
+            this->logger->logMsg("Object " + QString::number(ent->getId()) + " of class  " +
+                                 EntityHelper::getClassName(ent.data()) + " couldn't created!",
+                                 MsgType::WARNING);
+        }
+    }
+    return ok;
+}
+
 bool EntityManager::save(QSharedPointer<Entity> &entity,
                          const bool persistRelations, const bool ignoreHasChanged, const bool validate,
                          const bool relationsIgnoreHasChanged) {
@@ -210,6 +228,25 @@ bool EntityManager::save(QSharedPointer<Entity> &entity,
                             ignoreHasChanged, validate, relationsIgnoreHasChanged);
 }
 
+bool EntityManager::save(QList<QSharedPointer<Entity> > &entities,
+                         const bool persistRelations, const bool ignoreHasChanged, const bool validate,
+                         const bool relationsIgnoreHasChanged) {
+    bool ok = true;
+    foreach (QSharedPointer<Entity> entity, entities) {
+        auto merged = QList<Entity *>();
+        ok = this->saveObject(entity, merged, persistRelations,
+                              ignoreHasChanged, validate, relationsIgnoreHasChanged);
+        if (!ok) {
+            break;
+            this->logger->logMsg("Object " + QString::number(entity->getId()) +
+                                 " of class  " +
+                                 EntityHelper::getClassName(entity.data()) + " couldn't saved.",
+                                 MsgType::WARNING);
+        }
+    }
+    return ok;
+}
+
 bool EntityManager::startup(QString version, QStringList toInitialize,
                             bool createIndices) {
     QSharedPointer<Entity> dbm = QSharedPointer<DatabaseMigration>
@@ -311,17 +348,6 @@ QList<QHash<QString, QVariant> > EntityManager::selectBySql(
     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;
-}
-
 bool EntityManager::validate(QSharedPointer<Entity> &entity) {
     QList<ValidationRule> rules = entity->validationRules();
     QList<ErrorMsg> list = QList<ErrorMsg>();
@@ -521,14 +547,15 @@ void EntityManager::savePrePersistedRelations(const QSharedPointer<Entity>
 }
 
 void EntityManager::savePostPersistedRelations(const QSharedPointer<Entity>
-        &entity, QList<Entity *> &mergedObjects, bool ignoreHasChanged) {
+        &entity, QList<Entity *> &mergedObjects, bool ignoreHasChanged, bool newItem) {
     auto relations = EntityHelper::getRelationProperties(entity.data());
     for (auto i = relations.constBegin(); i != relations.constEnd(); ++i) {
         const Relation r = i.key();
         auto var = i.value().read(entity.data());
         if (!var.isNull()) {
             if (r.getType() == RelationType::MANY_TO_MANY) {
-                this->persistManyToMany(entity, r, var, mergedObjects, ignoreHasChanged);
+                this->persistManyToMany(entity, r, var, mergedObjects, ignoreHasChanged,
+                                        newItem);
             } else if (r.getType() == RelationType::ONE_TO_MANY) {
                 QList<QSharedPointer<Entity>> list = EntityInstanceFactory::castQVariantList(
                         var);
@@ -757,7 +784,7 @@ QList<Entity *> &mergedObjects) {
 
 void EntityManager::persistManyToMany(const QSharedPointer<Entity> &entity,
                                       const Relation &r, QVariant &property, QList<Entity *> &mergedObjects,
-                                      const bool ignoreHasChanged) {
+                                      const bool ignoreHasChanged, const bool newItem) {
     auto list = property.value<QList<QVariant>>();
     if (!list.isEmpty() && !(list.at(0).isNull())) {
         auto var = list.at(0);
@@ -765,10 +792,17 @@ void EntityManager::persistManyToMany(const QSharedPointer<Entity> &entity,
         auto builder = this->schema->getQueryBuilder();
         QString tblName = builder->generateManyToManyTableName(entity, ptr, r);
         if (this->schema->containsTable(tblName)) {
-            QSqlQuery q = builder->manyToManyDelete(
-                              tblName, builder->generateManyToManyColumnName(entity),
-                              entity->getProperty(entity->getPrimaryKey()).toLongLong());
-            if (this->db->exec(q)) {
+            bool ok = newItem;
+            QSqlQuery q;
+            if (!newItem) {
+                q = builder->manyToManyDelete(
+                        tblName, builder->generateManyToManyColumnName(entity),
+                        entity->getProperty(entity->getPrimaryKey()).toLongLong());
+                ok = this->db->exec(q);
+            } else {
+                q = builder->getQuery();
+            }
+            if (ok) {
                 auto nList = EntityInstanceFactory::castQVariantList(property);
                 this->persistMappedByRelation(nList, q, entity, ptr, r, tblName, mergedObjects);
             }
@@ -831,19 +865,6 @@ QList<QSharedPointer<Entity> > EntityManager::findEntityByAttributes(
     return this->convert(maps, EntityHelper::getClassname(entity.data()));
 }
 
-bool EntityManager::create(QList<QSharedPointer<Entity> > entities,
-                           const bool persistRelations, const bool validate,
-                           const bool relationsIgnoreHasChanged) {
-    bool ok = true;
-    foreach (QSharedPointer<Entity> ent, entities) {
-        ok = this->create(ent, persistRelations, validate, relationsIgnoreHasChanged);
-        if (!ok) {
-            break;
-        }
-    }
-    return ok;
-}
-
 QHash<QString, QVariant> EntityManager::findByPk(qint64 id,
         const QSharedPointer<Entity>
         &e) {
@@ -970,11 +991,31 @@ bool EntityManager::createTable(QString className, bool createRelationTables) {
     return this->schema->getQueryBuilder()->createTable(e, createRelationTables);
 }
 
-quint8 EntityManager::count(const QSharedPointer<Entity> &entity,
-                            bool ignoreID) {
+quint8 EntityManager::count(const QSharedPointer<Entity> &entity, bool ignoreID,
+                            bool followInheritance) {
+    Query q = Query();
+    auto qb = this->schema->getQueryBuilder();
+    QHash<QString, QVariant> values;
+    if (followInheritance) {
+        q.appendJoins(qb->joinBaseClasses(entity));
+        values = EntityHelper::getEntityAttributes(EntityHelper::getMetaProperties(
+                     entity.data()), entity);
+
+    } else {
+        values = EntityHelper::getEntityAttributes(
+                     EntityHelper::getNonInheritedMetaProperties(entity.data()), entity);
+    }
+    //maybe filter MANY_TO_MANY and ONE_TO_MANY relations
+    q.appendFrom(entity->getTablename());
+    q.appendWhere(qb->where(values, qb->andKeyword(), ignoreID,
+                            entity->getPrimaryKey(), false));
+    q.appendParams(values);
+    return this->count(q);
+}
+
+quint8 EntityManager::count(const QString &tableName) {
     qint8 rc = -1;
-    QSqlQuery q = this->schema->getQueryBuilder()->count(entity,
-                  ignoreID);
+    QSqlQuery q = this->schema->getQueryBuilder()->count(tableName);
     this->db->select(q);
     if (q.next()) {
         rc = q.value(0).toInt();
@@ -982,9 +1023,10 @@ quint8 EntityManager::count(const QSharedPointer<Entity> &entity,
     return rc;
 }
 
-quint8 EntityManager::count(const QString &tableName) {
-    qint8 rc = -1;
-    QSqlQuery q = this->schema->getQueryBuilder()->count(tableName);
+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();
diff --git a/src/entitymanager.h b/src/entitymanager.h
index 91abf87..8eaf35c 100644
--- a/src/entitymanager.h
+++ b/src/entitymanager.h
@@ -71,7 +71,8 @@ class EntityManager : public QObject {
      */
     bool create(QList<QSharedPointer<Entity>> entities,
                 const bool persistRelations = true, const bool validate = true,
-                const bool relationsIgnoreHasChanged = false);
+                const bool relationsIgnoreHasChanged = false,
+                const bool checkDuplicate = false);
     /**
      * @brief EntityManager::create
      * Will persist an entity in the database. Before its persisted it has the id -1(invalid id). If database persisting was succesfull it has a valid id.
@@ -96,6 +97,10 @@ class EntityManager : public QObject {
     bool save(QSharedPointer<Entity> &entity, const bool persistRelations = true,
               const bool ignoreHasChanged = false, const bool validate = true,
               const bool relationsIgnoreHasChanged = false);
+    bool save(QList<QSharedPointer<Entity>> &entities,
+              const bool persistRelations = true,
+              const bool ignoreHasChanged = false, const bool validate = true,
+              const bool relationsIgnoreHasChanged = false);
     bool merge(QSharedPointer<Entity> &entity, bool withRelations = true,
                const bool validate = true, const bool relationsIgnoreHasChanged = false);
     bool remove(QSharedPointer<Entity> &entity);
@@ -103,7 +108,8 @@ class EntityManager : public QObject {
     bool createTable(const QSharedPointer<Entity> &entity,
                      bool createRelationTables = true);
     bool createTable(QString className, bool createRelationTables = true);
-    quint8 count(const QSharedPointer<Entity> &entity, bool ignoreID = true);
+    quint8 count(const QSharedPointer<Entity> &entity, bool ignoreID = true,
+                 bool followInheritance = false);
     quint8 count(const QString &tableName);
     QSharedPointer<Database> getDb() const;
     void setDb(const QSharedPointer<Database> &value);
@@ -302,7 +308,7 @@ class EntityManager : public QObject {
                   const QVariant &id = "");
     void persistManyToMany(const QSharedPointer<Entity> &entity, const Relation &r,
                            QVariant &property, QList<Entity *> &mergedObjects,
-                           const bool ignoreHasChanged = false);
+                           const bool ignoreHasChanged = false, const bool newItem = false);
     QList<QHash<QString, QVariant> > findAllByAttributes(const
             QSharedPointer<Entity> &entity,
             bool ignoreID = false);
@@ -327,7 +333,8 @@ class EntityManager : public QObject {
      * @throw can throw in debug mode a QString exception when the type of any Relation is wrong @see EntityManager::checkRelation
      */
     void savePostPersistedRelations(const QSharedPointer<Entity> &entity,
-                                    QList<Entity *> &mergedObjects, bool ignoreHasChanged = false);
+                                    QList<Entity *> &mergedObjects, bool ignoreHasChanged = false,
+                                    bool newItem = false);
 
     QList<QSharedPointer<Entity>> saveRelationEntities(const
                                QList<QSharedPointer<Entity>> &list, const Relation &r,
diff --git a/src/querybuilder.cpp b/src/querybuilder.cpp
index d6bd538..bfb0800 100644
--- a/src/querybuilder.cpp
+++ b/src/querybuilder.cpp
@@ -629,18 +629,18 @@ QSqlQuery QueryBuilder::findId(const QSharedPointer<Entity> &entity) const {
     return q;
 }
 
-QSqlQuery QueryBuilder::count(const QSharedPointer<Entity> &entity,
-                              bool ignoreID) const {
-    QHash<QString, QVariant> values = EntityHelper::getEntityAttributes(
-                                          EntityHelper::getMetaProperties(entity.data()),
-                                          entity);
-    QSqlQuery q = this->database->getQuery(this->selectBase(QStringList(
-            entity->getTablename()),
-                                           QStringList(this->countFunction())) + this->where(
-                                                   values, this->andKeyword(), ignoreID));
-    this->bindValues(values, q, ignoreID);
-    return q;
-}
+//QSqlQuery QueryBuilder::count(const QSharedPointer<Entity> &entity,
+//                              bool ignoreID) const {
+//    QHash<QString, QVariant> values = EntityHelper::getEntityAttributes(
+//                                          EntityHelper::getMetaProperties(entity.data()),
+//                                          entity);
+//    QSqlQuery q = this->database->getQuery(this->selectBase(QStringList(
+//            entity->getTablename()),
+//                                           QStringList(this->countFunction())) + this->where(
+//                                                   values, this->andKeyword(), ignoreID));
+//    this->bindValues(values, q, ignoreID);
+//    return q;
+//}
 
 QSqlQuery QueryBuilder::count(const QString &tableName) const {
     QSqlQuery q = this->database->getQuery(this->selectBase(QStringList(
diff --git a/src/querybuilder.h b/src/querybuilder.h
index b798796..469541a 100644
--- a/src/querybuilder.h
+++ b/src/querybuilder.h
@@ -209,7 +209,7 @@ class QueryBuilder {
                       qint64 offset = 0);
     QList<QSqlQuery> remove(const QSharedPointer<Entity> &entity) const;
     QSqlQuery findId(const QSharedPointer<Entity> &entity) const;
-    QSqlQuery count(const QSharedPointer<Entity> &entity, bool ignoreID) const;
+    //QSqlQuery count(const QSharedPointer<Entity> &entity, bool ignoreID) const;
     QSqlQuery count(const QString &tableName) const;
     QList<QSqlQuery> merge(const QSharedPointer<Entity> &entity) const;
     QList<QSqlQuery> create(const QSharedPointer<Entity> &entity) const;
@@ -267,7 +267,7 @@ class QueryBuilder {
                   const QString &conjunction,
                   bool ignoreID = false, const QString &primaryKey = "id",
                   bool withKeyword = true) const;
-    QString attributes(const QHash<QString, QVariant> &m, bool select=true,
+    QString attributes(const QHash<QString, QVariant> &m, bool select = true,
                        const QString &conjunction = ",",
                        bool ignoreID = false, const QString &primaryKey = "id") const;
     QHash<QString, QVariant> saveAttributes(const QSharedPointer<Entity> &entity,
diff --git a/src/queryinterpreter.cpp b/src/queryinterpreter.cpp
index 890b736..d4ba01b 100644
--- a/src/queryinterpreter.cpp
+++ b/src/queryinterpreter.cpp
@@ -62,12 +62,12 @@ QString QueryInterpreter::buildSelect(Query &q,
                                       const QList<Expression> &columns,
                                       const bool &distinct, const QString &selectOption) const {
     QString sqlSelect = distinct ? ("SELECT " + this->builder->distinct()) :
-                        "SELECT";
+                        "SELECT ";
     if (!selectOption.isEmpty()) {
-        sqlSelect += this->builder->getSeparator() + selectOption;
+        sqlSelect += this->builder->getSeparator() + selectOption + " ";
     }
     if (columns.isEmpty()) {
-        return sqlSelect + " *";
+        return sqlSelect + "*";
     }
     bool first = true;
     for (int i = 0; i < columns.size(); ++i) {
