[SCM] Akonadi packaging branch, master, updated. debian/1.13.0-6-1-g93b22bd

Dmitry Smirnov onlyjob at moszumanska.debian.org
Mon Jul 20 03:23:29 UTC 2015


Gitweb-URL: http://git.debian.org/?p=pkg-kde/kde-req/akonadi.git;a=commitdiff;h=93b22bd

The following commit has been merged in the master branch:
commit 93b22bdf7172db48d7e670f751fcc353f39346e7
Author: Dmitry Smirnov <onlyjob at member.fsf.org>
Date:   Mon Jul 20 12:34:09 2015 +1000

    Drop patches introduced in previous upload due to regressions
    causing invalid SQL commands.
---
 debian/changelog                                   |   8 +
 debian/patches/series                              |   3 -
 ...001-skip-value-condition-on-invalid-flags.patch |  38 ---
 .../upstream_opt-0006-cache-PartTypes.patch        | 261 --------------
 ...7-avoid-recursive-listing-in-SearchHelper.patch | 374 ---------------------
 5 files changed, 8 insertions(+), 676 deletions(-)

diff --git a/debian/changelog b/debian/changelog
index 0aad6e9..7213b06 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+akonadi (1.13.0-7) unstable; urgency=medium
+
+  * Team upload.
+  * Removed some patches introduced in previous upload due to regressions
+    causing invalid SQL commands.
+
+ -- Dmitry Smirnov <onlyjob at debian.org>  Mon, 20 Jul 2015 12:30:32 +1000
+
 akonadi (1.13.0-6) unstable; urgency=medium
 
   * Team upload.
diff --git a/debian/patches/series b/debian/patches/series
index 9101dec..b64faf0 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -8,10 +8,7 @@ upstream-prevent-QTimer-negative-interval.patch
 upstream-use-QAtomicInt.patch
 upstream_dont_call_insert_from_Q_ASSERT.patch
 upstream_dont_leak_old_external_payload_files.patch
-upstream_opt-0001-skip-value-condition-on-invalid-flags.patch
 upstream_opt-0002-intern-entity-strings.patch
 upstream_opt-0003-QMutexLocker.patch
 upstream_opt-0004-one-hash-lookup.patch
 upstream_opt-0005-optimize-queries.patch
-upstream_opt-0006-cache-PartTypes.patch
-upstream_opt-0007-avoid-recursive-listing-in-SearchHelper.patch
diff --git a/debian/patches/upstream_opt-0001-skip-value-condition-on-invalid-flags.patch b/debian/patches/upstream_opt-0001-skip-value-condition-on-invalid-flags.patch
deleted file mode 100644
index 786eb96..0000000
--- a/debian/patches/upstream_opt-0001-skip-value-condition-on-invalid-flags.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From 7cbff48f5782d1f7f844678e6b785aeb419b0c47 Mon Sep 17 00:00:00 2001
-From: Milian Wolff <mail at milianw.de>
-Date: Mon, 1 Dec 2014 11:59:12 +0100
-Subject: [PATCH] Optimize: Skip value condition on invalid flags.
-
-HandlerHelper::itemWithFlagsCount gets called quite often apparently
-and I noticed that it was relatively slow from the Query Debugger
-in Akonadi Console. EXPLAIN'ing the query showed that it was using
-a slow-path for the WHERE FOO AND (BAR OR ASDF) condition. Here,
-ASDF was always id = -1, the id of the $IGNORED flag, which
-I apparently don't have. Getting rid of that condition simplifies
-the query to WHERE FOO AND BAR, which is apparently much better
-optimizable. Before, the query often showed a runtime of ~15ms.
-Now it is down to ~9ms.
-
-REVIEW: 121306
----
- server/src/handlerhelper.cpp | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/server/src/handlerhelper.cpp b/server/src/handlerhelper.cpp
-index 634a26c..82347b4 100644
---- a/server/src/handlerhelper.cpp
-+++ b/server/src/handlerhelper.cpp
-@@ -123,6 +123,10 @@ int HandlerHelper::itemWithFlagsCount( const Collection &col, const QStringList
-   // it hits an in-memory cache.
-   Q_FOREACH ( const QString &flag, flags ) {
-     const Flag f = Flag::retrieveByName( flag );
-+    if (!f.isValid()) {
-+      // since we OR this condition, we can skip invalid flags to speed up the query
-+      continue;
-+    }
-     cond.addValueCondition( PimItemFlagRelation::rightFullColumnName(), Query::Equals, f.id() );
-   }
-   qb.addCondition( cond );
--- 
-2.1.4
-
diff --git a/debian/patches/upstream_opt-0006-cache-PartTypes.patch b/debian/patches/upstream_opt-0006-cache-PartTypes.patch
deleted file mode 100644
index 51d1f7e..0000000
--- a/debian/patches/upstream_opt-0006-cache-PartTypes.patch
+++ /dev/null
@@ -1,261 +0,0 @@
-From 215b188d891d5236fe94131d176d7ddc3ae02d5d Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Dan=20Vr=C3=A1til?= <dvratil at redhat.com>
-Date: Fri, 5 Dec 2014 17:12:28 +0100
-Subject: [PATCH] Avoid ridiculous amount of SQL queries by caching PartTypes
-
-PartTypes are identified by their FQ name, which is in form NAMESPACE:NAME,
-where namespace and name are stored in individual columns. For this reason
-the standard ::retrieveByName() and name cache generated from entities.xslt
-does not work. This patch adds special handling for PartType table, so that
-a special PartType::retrieveByFQName() method as well as PartType name cache
-handling are generated during the XSL Transformation, allowing us to cache
-all the PartTypes.
-
-This reduces the amount of SQL queries by at least two for each single AKAPPEND,
-MERGE, STORE and FETCH command, providing a nice performance boost during
-sync.
----
- server/src/handler/append.cpp          |  4 ++--
- server/src/storage/datastore.cpp       |  4 +++-
- server/src/storage/entities-header.xsl |  7 ++++++-
- server/src/storage/entities-source.xsl | 31 ++++++++++++++++++++++++++++++-
- server/src/storage/entities.xsl        |  7 ++++++-
- server/src/storage/parttypehelper.cpp  | 29 +----------------------------
- server/src/storage/parttypehelper.h    | 13 -------------
- 7 files changed, 48 insertions(+), 47 deletions(-)
-
-diff --git a/server/src/handler/append.cpp b/server/src/handler/append.cpp
-index c503216..b594e27 100644
---- a/server/src/handler/append.cpp
-+++ b/server/src/handler/append.cpp
-@@ -134,7 +134,7 @@ bool Append::commit()
- 
-     // wrap data into a part
-     Part part;
--    part.setPartType( PartTypeHelper::fromName( "PLD", "RFC822" ) );
-+    part.setPartType( PartType::retrieveByFQName( QLatin1String("PLD"), QLatin1String("RFC822") ) );
-     part.setData( m_data );
-     part.setPimItemId( item.id() );
-     part.setDatasize( dataSize );
-@@ -148,7 +148,7 @@ bool Append::commit()
-     //akDebug() << "Append handler: doPreprocessing is" << doPreprocessing;
-     if ( doPreprocessing ) {
-       Part hiddenAttribute;
--      hiddenAttribute.setPartType( PartTypeHelper::fromName( "ATR", "HIDDEN" ) );
-+      hiddenAttribute.setPartType( PartType::retrieveByFQName( QLatin1String("ATR"), QLatin1String("HIDDEN") ) );
-       hiddenAttribute.setData( QByteArray() );
-       hiddenAttribute.setPimItemId( item.id() );
-       hiddenAttribute.setDatasize( 0 );
-diff --git a/server/src/storage/datastore.cpp b/server/src/storage/datastore.cpp
-index ae78bab..304f0e8 100644
---- a/server/src/storage/datastore.cpp
-+++ b/server/src/storage/datastore.cpp
-@@ -183,6 +183,7 @@ bool DataStore::init()
-   Flag::enableCache( true );
-   Resource::enableCache( true );
-   Collection::enableCache( true );
-+  PartType::enableCache( true );
- 
-   return true;
- }
-@@ -1025,7 +1026,8 @@ bool DataStore::unhideAllPimItems()
-   akDebug() << "DataStore::unhideAllPimItems()";
- 
-   try {
--    return PartHelper::remove( Part::partTypeIdFullColumnName(), PartTypeHelper::fromName( "ATR", "HIDDEN" ).id() );
-+    return PartHelper::remove( Part::partTypeIdFullColumnName(),
-+                               PartType::retrieveByFQName( QLatin1String("ATR"), QLatin1String("HIDDEN") ).id() );
-   } catch ( ... ) {} // we can live with this failing
- 
-   return false;
-diff --git a/server/src/storage/entities-header.xsl b/server/src/storage/entities-header.xsl
-index 4966966..d515fd3 100644
---- a/server/src/storage/entities-header.xsl
-+++ b/server/src/storage/entities-header.xsl
-@@ -133,11 +133,16 @@ class <xsl:value-of select="$className"/> : private Entity
-     <xsl:text>static </xsl:text><xsl:value-of select="$className"/> retrieveById( qint64 id );
-     </xsl:if>
- 
--    <xsl:if test="column[@name = 'name']">
-+    <xsl:if test="column[@name = 'name'] and $className != 'PartType'">
-     /** Returns the record with name @p name. */
-     <xsl:text>static </xsl:text><xsl:value-of select="$className"/> retrieveByName( const <xsl:value-of select="column[@name = 'name']/@type"/> &name );
-     </xsl:if>
- 
-+    <xsl:if test="column[@name = 'name'] and $className = 'PartType'">
-+    <!-- Special case for PartTypes, which are identified by "NS:NAME" -->
-+    <xsl:text>static PartType retrieveByFQName( const QString &ns, const QString &name );</xsl:text>
-+    </xsl:if>
-+
-     /** Retrieve all records from this table. */
-     static <xsl:value-of select="$className"/>::List retrieveAll();
-     /** Retrieve all records with value @p value in column @p key. */
-diff --git a/server/src/storage/entities-source.xsl b/server/src/storage/entities-source.xsl
-index e398da5..46ef3a6 100644
---- a/server/src/storage/entities-source.xsl
-+++ b/server/src/storage/entities-source.xsl
-@@ -130,7 +130,15 @@ void <xsl:value-of select="$className"/>::Private::addToCache( const <xsl:value-
-   idCache.insert( entry.id(), entry );
-   </xsl:if>
-   <xsl:if test="column[@name = 'name']">
-+    <xsl:choose>
-+     <xsl:when test="$className = 'PartType'">
-+      <!-- special case for PartType, which is identified as "NS:NAME" -->
-+  nameCache.insert( entry.ns() + QLatin1Char(':') + entry.name(), entry );
-+      </xsl:when>
-+      <xsl:otherwise>
-   nameCache.insert( entry.name(), entry );
-+      </xsl:otherwise>
-+    </xsl:choose>
-   </xsl:if>
- }
- 
-@@ -323,7 +331,7 @@ QVector< <xsl:value-of select="$className"/> > <xsl:value-of select="$clas
- }
- 
- </xsl:if>
--<xsl:if test="column[@name = 'name']">
-+<xsl:if test="column[@name = 'name'] and $className != 'PartType'">
- <xsl:value-of select="$className"/><xsl:text> </xsl:text><xsl:value-of select="$className"/>::retrieveByName( const <xsl:value-of select="column[@name = 'name']/@type"/> &name )
- {
-   <xsl:call-template name="data-retrieval">
-@@ -333,6 +341,19 @@ QVector< <xsl:value-of select="$className"/> > <xsl:value-of select="$clas
- }
- </xsl:if>
- 
-+<xsl:if test="column[@name = 'name'] and $className = 'PartType'">
-+<xsl:text>PartType PartType::retrieveByFQName( const QString & ns, const QString & name )</xsl:text>
-+{
-+  const QString fqname = ns + QLatin1Char(':') + name;
-+  <xsl:call-template name="data-retrieval">
-+  <xsl:with-param name="key">ns</xsl:with-param>
-+  <xsl:with-param name="key2">name</xsl:with-param>
-+  <xsl:with-param name="lookupKey">fqname</xsl:with-param>
-+  <xsl:with-param name="cache">nameCache</xsl:with-param>
-+  </xsl:call-template>
-+}
-+</xsl:if>
-+
- QVector<<xsl:value-of select="$className"/>> <xsl:value-of select="$className"/>::retrieveAll()
- {
-   QSqlDatabase db = DataStore::self()->database();
-@@ -588,7 +609,15 @@ void <xsl:value-of select="$className"/>::invalidateCache() const
-     Private::idCache.remove( id() );
-     </xsl:if>
-     <xsl:if test="column[@name = 'name']">
-+      <xsl:choose>
-+        <xsl:when test="$className = 'PartType'">
-+        <!-- Special handling for PartType, which is identified as "NS:NAME" -->
-+    Private::nameCache.remove( ns() + QLatin1Char(':') + name() );
-+        </xsl:when>
-+        <xsl:otherwise>
-     Private::nameCache.remove( name() );
-+        </xsl:otherwise>
-+      </xsl:choose>
-     </xsl:if>
-   }
- }
-diff --git a/server/src/storage/entities.xsl b/server/src/storage/entities.xsl
-index c8fb1fd..2cf96c4 100644
---- a/server/src/storage/entities.xsl
-+++ b/server/src/storage/entities.xsl
-@@ -169,12 +169,14 @@ set<xsl:value-of select="$methodName"/>( <xsl:call-template name="argument"/> )
- <!-- data retrieval for a given key field -->
- <xsl:template name="data-retrieval">
- <xsl:param name="key"/>
-+<xsl:param name="key2"/>
-+<xsl:param name="lookupKey" select="$key"/>
- <xsl:param name="cache"/>
- <xsl:variable name="className"><xsl:value-of select="@name"/></xsl:variable>
-   <xsl:if test="$cache != ''">
-   if ( Private::cacheEnabled ) {
-     QMutexLocker lock(&Private::cacheMutex);
--    QHash<<xsl:value-of select="column[@name = $key]/@type"/>, <xsl:value-of select="$className"/>>::const_iterator it = Private::<xsl:value-of select="$cache"/>.constFind(<xsl:value-of select="$key"/>);
-+    QHash<<xsl:value-of select="column[@name = $key]/@type"/>, <xsl:value-of select="$className"/>>::const_iterator it = Private::<xsl:value-of select="$cache"/>.constFind(<xsl:value-of select="$lookupKey"/>);
-     if ( it != Private::<xsl:value-of select="$cache"/>.constEnd() ) {
-       return it.value();
-     }
-@@ -188,6 +190,9 @@ set<xsl:value-of select="$methodName"/>( <xsl:call-template name="argument"/> )
-   static const QStringList columns = removeEntry(columnNames(), <xsl:value-of select="$key"/>Column());
-   qb.addColumns( columns );
-   qb.addValueCondition( <xsl:value-of select="$key"/>Column(), Query::Equals, <xsl:value-of select="$key"/> );
-+  <xsl:if test="$key2 != ''">
-+  qb.addValueCondition( <xsl:value-of select="$key2"/>Column(), Query::Equals, <xsl:value-of select="$key2"/> );
-+  </xsl:if>
-   if ( !qb.exec() ) {
-     akDebug() << "Error during selection of record with <xsl:value-of select="$key"/>"
-       << <xsl:value-of select="$key"/> << "from table" << tableName()
-diff --git a/server/src/storage/parttypehelper.cpp b/server/src/storage/parttypehelper.cpp
-index b73dcd5..7654108 100644
---- a/server/src/storage/parttypehelper.cpp
-+++ b/server/src/storage/parttypehelper.cpp
-@@ -37,7 +37,7 @@ QPair< QString, QString > PartTypeHelper::parseFqName(const QString& fqName)
- PartType PartTypeHelper::fromFqName(const QString& fqName)
- {
-   const QPair<QString, QString> p = parseFqName( fqName );
--  return fromName( p.first, p.second );
-+  return PartType::retrieveByFQName(p.first, p.second);
- }
- 
- PartType PartTypeHelper::fromFqName(const QByteArray& fqName)
-@@ -45,33 +45,6 @@ PartType PartTypeHelper::fromFqName(const QByteArray& fqName)
-   return fromFqName( QLatin1String(fqName) );
- }
- 
--PartType PartTypeHelper::fromName(const QString& ns, const QString& typeName)
--{
--  SelectQueryBuilder<PartType> qb;
--  qb.addValueCondition( PartType::nsColumn(), Query::Equals, ns );
--  qb.addValueCondition( PartType::nameColumn(), Query::Equals, typeName );
--  if ( !qb.exec() )
--    throw PartTypeException( "Unable to query part type table." );
--  const PartType::List result = qb.result();
--  if ( result.size() == 1 )
--    return result.first();
--  if ( result.size() > 1 )
--    throw PartTypeException( "Part type uniqueness constraint violation." );
--
--  // doesn't exist yet, so let's create a new one
--  PartType type;
--  type.setName( typeName );
--  type.setNs( ns );
--  if ( !type.insert() )
--    throw PartTypeException( "Creating a new part type failed." );
--  return type;
--}
--
--PartType PartTypeHelper::fromName(const char* ns, const char* typeName)
--{
--  return fromName( QLatin1String(ns), QLatin1String(typeName) );
--}
--
- Query::Condition PartTypeHelper::conditionFromFqName(const QString& fqName)
- {
-   const QPair<QString, QString> p = parseFqName( fqName );
-diff --git a/server/src/storage/parttypehelper.h b/server/src/storage/parttypehelper.h
-index 38cb858..4c4f42f 100644
---- a/server/src/storage/parttypehelper.h
-+++ b/server/src/storage/parttypehelper.h
-@@ -48,19 +48,6 @@ namespace PartTypeHelper
-   PartType fromFqName( const QByteArray &fqName );
- 
-   /**
--   * Retrieve (or create) PartType for the given namespace and type name.
--   * @param ns Namespace
--   * @param typeName Part type name.
--   * @throws PartTypeException
--   */
--  PartType fromName( const QString &ns, const QString &typeName );
--
--  /**
--   * Convenience overload of the above.
--   */
--  PartType fromName( const char *ns, const char *typeName );
--
--  /**
-    * Returns a query condition that matches the given part.
-    * @param fqName fully-qualified part type name
-    * @throws PartTypeException
--- 
-2.1.4
-
diff --git a/debian/patches/upstream_opt-0007-avoid-recursive-listing-in-SearchHelper.patch b/debian/patches/upstream_opt-0007-avoid-recursive-listing-in-SearchHelper.patch
deleted file mode 100644
index eebf493..0000000
--- a/debian/patches/upstream_opt-0007-avoid-recursive-listing-in-SearchHelper.patch
+++ /dev/null
@@ -1,374 +0,0 @@
-From 059d52845cbbc10e882764f64245c5995af4e741 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Dan=20Vr=C3=A1til?= <dvratil at redhat.com>
-Date: Mon, 8 Dec 2014 13:49:27 +0100
-Subject: [PATCH] Avoid recursive collection listing in SearchHelper
-
-The recursive listing generates one SQL query per collection, and since search
-is invoked rather often (basically whenever you open an email in KMail), we get
-lots of unnecessary queries. This new algorithm does one query to fetch all
-folders with matching mime types, and only falls back to query the parent chain
-when the requested ancestor is not 0 (root), or when the result collection is
-not a direct descendant of the requested ancestor.
----
- server/src/handler/search.cpp        |   4 +-
- server/src/handler/searchhelper.cpp  | 111 ++++++++++++++----------
- server/src/handler/searchhelper.h    |   2 +-
- server/src/search/searchmanager.cpp  |   2 +-
- server/tests/unittest/CMakeLists.txt |   2 +
- server/tests/unittest/searchtest.cpp | 158 +++++++++++++++++++++++++++++++++++
- 6 files changed, 230 insertions(+), 49 deletions(-)
- create mode 100644 server/tests/unittest/searchtest.cpp
-
-diff --git a/server/src/handler/search.cpp b/server/src/handler/search.cpp
-index 06d172f..00484ff 100644
---- a/server/src/handler/search.cpp
-+++ b/server/src/handler/search.cpp
-@@ -95,9 +95,7 @@ bool Search::parseStream()
-     }
- 
-     if ( recursive ) {
--      Q_FOREACH ( qint64 collection, collectionIds ) {
--        collections << SearchHelper::listCollectionsRecursive( QVector<qint64>() << collection, mimeTypes );
--      }
-+      collections << SearchHelper::matchSubcollectionsByMimeType( collectionIds, mimeTypes );
-     } else {
-       collections = collectionIds;
-     }
-diff --git a/server/src/handler/searchhelper.cpp b/server/src/handler/searchhelper.cpp
-index aa6694d..1a06c0e 100644
---- a/server/src/handler/searchhelper.cpp
-+++ b/server/src/handler/searchhelper.cpp
-@@ -20,6 +20,7 @@
- 
- #include "searchhelper.h"
- #include "storage/countquerybuilder.h"
-+#include <storage/queryhelper.h>
- #include "entities.h"
- 
- #include <libs/protocol_p.h>
-@@ -89,55 +90,77 @@ QString SearchHelper::extractMimetype( const QList<QByteArray> &junks, int start
- }
- 
- 
--QVector<qint64> SearchHelper::listCollectionsRecursive( const QVector<qint64> &ancestors, const QStringList &mimeTypes )
-+static qint64 parentCollectionId(qint64 collectionId)
- {
--  QVector<qint64> recursiveChildren;
--  Q_FOREACH ( qint64 ancestor, ancestors ) {
--    QVector<qint64> searchChildren;
--
--    { // Free the query before entering recursion to prevent too many opened connections
--
--      Query::Condition mimeTypeCondition;
--      mimeTypeCondition.addColumnCondition( CollectionMimeTypeRelation::rightFullColumnName(), Query::Equals, MimeType::idFullColumnName() );
--      // Exclude top-level collections and collections that cannot have items!
--      mimeTypeCondition.addValueCondition( MimeType::nameFullColumnName(), Query::NotEquals, QLatin1String( "inode/directory" ) );
--      if ( !mimeTypes.isEmpty() ) {
--        mimeTypeCondition.addValueCondition( MimeType::nameFullColumnName(), Query::In, mimeTypes );
--      }
-+    QueryBuilder qb(Collection::tableName(), QueryBuilder::Select);
-+    qb.addColumn(Collection::parentIdColumn());
-+    qb.addValueCondition(Collection::idColumn(), Query::Equals, collectionId);
-+    if (!qb.exec()) {
-+        return -1;
-+    }
-+    if (!qb.query().next()) {
-+        return -1;
-+    }
-+    return qb.query().value(0).toLongLong();
-+}
- 
--      CountQueryBuilder qb( Collection::tableName(), MimeType::nameFullColumnName(), CountQueryBuilder::All );
--      qb.addColumn( Collection::idFullColumnName() );
--      qb.addJoin( QueryBuilder::LeftJoin, CollectionMimeTypeRelation::tableName(), CollectionMimeTypeRelation::leftFullColumnName(), Collection::idFullColumnName() );
--      qb.addJoin( QueryBuilder::LeftJoin, MimeType::tableName(), mimeTypeCondition );
--      if ( ancestor == 0 ) {
--        qb.addValueCondition( Collection::parentIdFullColumnName(), Query::Is, QVariant() );
--      } else {
--        // Also include current ancestor's result, so that we know whether we should search in the ancestor too
--        Query::Condition idCond( Query::Or );
--        idCond.addValueCondition( Collection::parentIdFullColumnName(), Query::Equals, ancestor );
--        idCond.addValueCondition( Collection::idFullColumnName(), Query::Equals, ancestor );
--        qb.addCondition( idCond );
--      }
--      qb.addValueCondition( Collection::isVirtualFullColumnName(), Query::Equals, false );
--      qb.addGroupColumn( Collection::idFullColumnName() );
--      qb.exec();
--
--      QSqlQuery query = qb.query();
--      while ( query.next() ) {
--        const qint64 id = query.value( 1 ).toLongLong();
--        // Don't add ancestor into search children, we are resolving it right now
--        if ( id != ancestor ) {
--          searchChildren << id;
-+
-+QVector<qint64> SearchHelper::matchSubcollectionsByMimeType(const QVector<qint64> &ancestors, const QStringList &mimeTypes)
-+{
-+    // Get all collections with given mime types
-+    QueryBuilder qb(Collection::tableName(), QueryBuilder::Select);
-+    qb.setDistinct(true);
-+    qb.addColumn(Collection::idFullColumnName());
-+    qb.addColumn(Collection::parentIdFullColumnName());
-+    qb.addJoin(QueryBuilder::LeftJoin, CollectionMimeTypeRelation::tableName(),
-+               CollectionMimeTypeRelation::leftFullColumnName(), Collection::idFullColumnName());
-+    qb.addJoin(QueryBuilder::LeftJoin, MimeType::tableName(),
-+               CollectionMimeTypeRelation::rightFullColumnName(), MimeType::idFullColumnName());
-+    Query::Condition cond(Query::Or);
-+    Q_FOREACH (const QString &mt, mimeTypes) {
-+        cond.addValueCondition(MimeType::nameFullColumnName(), Query::Equals, mt);
-+    }
-+    qb.addCondition(cond);
-+
-+    if (!qb.exec()) {
-+        qWarning() << "Failed to query search collections";
-+        return QVector<qint64>();
-+    }
-+
-+    QMap<qint64 /* parentId */, QVector<qint64> /* collectionIds */> candidateCollections;
-+    while (qb.query().next()) {
-+        candidateCollections[qb.query().value(1).toLongLong()].append(qb.query().value(0).toLongLong());
-+    }
-+
-+    // If the ancestors list contains root, then return what we got, since everything
-+    // is sub collection of root
-+    QVector<qint64> results;
-+    if (ancestors.contains(0)) {
-+        Q_FOREACH (const QVector<qint64> &res, candidateCollections.values()) {
-+            results += res;
-         }
--        if ( query.value( 0 ).toInt() > 0 ) { // count( mimeTypeTable.name ) > 0
--          recursiveChildren << id;
-+        return results;
-+    }
-+
-+    // Try to resolve direct descendants
-+    Q_FOREACH (qint64 ancestor, ancestors) {
-+        const QVector<qint64> cols = candidateCollections.take(ancestor);
-+        if (!cols.isEmpty()) {
-+            results += cols;
-         }
--      }
-     }
--    if ( !searchChildren.isEmpty() ) {
--      recursiveChildren << listCollectionsRecursive( searchChildren, mimeTypes );
-+
-+    for (auto iter = candidateCollections.begin(); iter != candidateCollections.end(); ++iter) {
-+        // Traverse the collection chain up to root
-+        qint64 parentId = iter.key();
-+        while (!ancestors.contains(parentId) && parentId > 0) {
-+            parentId = parentCollectionId(parentId);
-+        }
-+        // Ok, we found a requested ancestor in the parent chain
-+        if (parentId > 0) {
-+            results += iter.value();
-+        }
-     }
--  }
- 
--  return recursiveChildren;
-+    return results;
- }
-diff --git a/server/src/handler/searchhelper.h b/server/src/handler/searchhelper.h
-index a64bb61..1595501 100644
---- a/server/src/handler/searchhelper.h
-+++ b/server/src/handler/searchhelper.h
-@@ -33,7 +33,7 @@ class SearchHelper
-   public:
-     static QList<QByteArray> splitLine( const QByteArray &line );
-     static QString extractMimetype( const QList<QByteArray> &junks, int start );
--    static QVector<qint64> listCollectionsRecursive( const QVector<qint64> &ancestors, const QStringList &mimeTypes );
-+    static QVector<qint64> matchSubcollectionsByMimeType( const QVector<qint64> &ancestors, const QStringList &mimeTypes );
- };
- 
- } // namespace Server
-diff --git a/server/src/search/searchmanager.cpp b/server/src/search/searchmanager.cpp
-index c821aa3..b940fcc 100644
---- a/server/src/search/searchmanager.cpp
-+++ b/server/src/search/searchmanager.cpp
-@@ -296,7 +296,7 @@ void SearchManager::updateSearchImpl( const Collection &collection, QWaitConditi
-   }
- 
-   if ( recursive ) {
--    queryCollections = SearchHelper::listCollectionsRecursive( queryAncestors, queryMimeTypes );
-+    queryCollections = SearchHelper::matchSubcollectionsByMimeType( queryAncestors, queryMimeTypes );
-   } else {
-     queryCollections = queryAncestors;
-   }
-diff --git a/server/tests/unittest/CMakeLists.txt b/server/tests/unittest/CMakeLists.txt
-index b9744d9..acdc180 100644
---- a/server/tests/unittest/CMakeLists.txt
-+++ b/server/tests/unittest/CMakeLists.txt
-@@ -77,3 +77,5 @@ add_server_test(listhandlertest.cpp akonadiprivate)
- add_server_test(modifyhandlertest.cpp akonadiprivate)
- add_server_test(createhandlertest.cpp akonadiprivate)
- add_server_test(collectionreferencetest.cpp akonadiprivate)
-+
-+add_server_test(searchtest.cpp akonadiprivate)
-\ No newline at end of file
-diff --git a/server/tests/unittest/searchtest.cpp b/server/tests/unittest/searchtest.cpp
-new file mode 100644
-index 0000000..f523b09
---- /dev/null
-+++ b/server/tests/unittest/searchtest.cpp
-@@ -0,0 +1,158 @@
-+/*
-+ * Copyright (C) 2014  Daniel Vrátil <dvratil at redhat.com>
-+ *
-+ * This library 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; either
-+ * version 2.1 of the License, or (at your option) any later version.
-+ *
-+ * This library 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
-+ * Lesser General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public
-+ * License along with this library; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-+ *
-+ */
-+
-+#include "fakeakonadiserver.h"
-+#include "searchhelper.h"
-+#include "akdebug.h"
-+#include "aktest.h"
-+
-+#include <entities.h>
-+
-+#include <QTest>
-+
-+using namespace Akonadi::Server;
-+
-+Q_DECLARE_METATYPE(QList<qint64>)
-+Q_DECLARE_METATYPE(QList<QString>)
-+
-+
-+class SearchTest : public QObject
-+{
-+    Q_OBJECT
-+
-+public:
-+    SearchTest()
-+        : QObject()
-+    {
-+        try {
-+            FakeAkonadiServer::instance()->setPopulateDb(false);
-+            FakeAkonadiServer::instance()->init();
-+        } catch (const FakeAkonadiServerException &e) {
-+            akError() << "Server exception: " << e.what();
-+            akFatal() << "Fake Akonadi Server failed to start up, aborting test";
-+        }
-+    }
-+
-+    ~SearchTest()
-+    {
-+        FakeAkonadiServer::instance()->quit();
-+    }
-+
-+    Collection createCollection(const Resource &res, const QString &name, const Collection &parent, const QStringList &mimetypes)
-+    {
-+        Collection col;
-+        col.setName(name);
-+        col.setResource(res);
-+        col.setParentId(parent.isValid() ? parent.id() : 0);
-+        col.insert();
-+        Q_FOREACH (const QString &mimeType, mimetypes) {
-+            MimeType mt = MimeType::retrieveByName(mimeType);
-+            if (!mt.isValid()) {
-+                mt = MimeType(mimeType);
-+                mt.insert();
-+            }
-+            col.addMimeType(mt);
-+        }
-+        return col;
-+    }
-+
-+private Q_SLOTS:
-+    void testSearchHelperCollectionListing_data()
-+    {
-+        /*
-+        Fake Resource
-+          |- Col 1 (inode/directory)
-+          |  |- Col 2 (inode/direcotry, application/octet-stream)
-+          |  |  |- Col 3(application/octet-stream)
-+          |  |- Col 4 (text/plain)
-+          |- Col 5 (inode/directory, text/plain)
-+             |- Col 6 (inode/directory, application/octet-stream)
-+             |- Col 7 (inode/directory, text/plain)
-+                 |- Col 8 (inode/directory, application/octet-stream)
-+                    |- Col 9 (unique/mime-type)
-+        */
-+
-+        Resource res(QLatin1String("Test Resource"), false);
-+        res.insert();
-+
-+        Collection col1 = createCollection(res, QLatin1String("Col 1"), Collection(),
-+                                           QStringList() << QLatin1String("inode/directory"));
-+        Collection col2 = createCollection(res, QLatin1String("Col 2"), col1,
-+                                           QStringList() << QLatin1String("inode/directory")
-+                                                         << QLatin1String("application/octet-stream"));
-+        Collection col3 = createCollection(res, QLatin1String("Col 3"), col2,
-+                                           QStringList() << QLatin1String("application/octet-stream"));
-+        Collection col4 = createCollection(res, QLatin1String("Col 4"), col2,
-+                                           QStringList() << QLatin1String("text/plain"));
-+        Collection col5 = createCollection(res, QLatin1String("Col 5"), Collection(),
-+                                           QStringList() << QLatin1String("inode/directory")
-+                                                         << QLatin1String("text/plain"));
-+        Collection col6 = createCollection(res, QLatin1String("Col 6"), col5,
-+                                           QStringList() << QLatin1String("inode/directory")
-+                                                         << QLatin1String("application/octet-stream"));
-+        Collection col7 = createCollection(res, QLatin1String("Col 7"), col5,
-+                                           QStringList() << QLatin1String("inode/directory")
-+                                                         << QLatin1String("text/plain"));
-+        Collection col8 = createCollection(res, QLatin1String("Col 8"), col7,
-+                                           QStringList() << QLatin1String("text/directory")
-+                                                         << QLatin1String("application/octet-stream"));
-+        Collection col9 = createCollection(res, QLatin1String("Col 9"), col8,
-+                                           QStringList() << QLatin1String("unique/mime-type"));
-+
-+        QTest::addColumn<QVector<qint64>>("ancestors");
-+        QTest::addColumn<QStringList>("mimetypes");
-+        QTest::addColumn<QVector<qint64>>("expectedResults");
-+
-+        QTest::newRow("") << QVector<qint64>({ 0 })
-+                          << QStringList({ QLatin1String("text/plain") })
-+                          << QVector<qint64>({ col4.id(), col5.id(), col7.id() });
-+        QTest::newRow("") << QVector<qint64>({ 0 })
-+                          << QStringList({ QLatin1String("application/octet-stream") })
-+                          << QVector<qint64>({ col2.id(), col3.id(), col6.id(), col8.id() });
-+        QTest::newRow("") << QVector<qint64>({ col1.id() })
-+                          << QStringList({ QLatin1String("text/plain") })
-+                          << QVector<qint64>({ col4.id() });
-+        QTest::newRow("") << QVector<qint64>({ col1.id() })
-+                          << QStringList({ QLatin1String("unique/mime-type") })
-+                          << QVector<qint64>();
-+        QTest::newRow("") << QVector<qint64>({ col2.id(), col7.id() })
-+                          << QStringList({ QLatin1String("application/octet-stream") })
-+                          << QVector<qint64>({ col3.id(), col8.id() });
-+    }
-+
-+    void testSearchHelperCollectionListing()
-+    {
-+        QFETCH(QVector<qint64>, ancestors);
-+        QFETCH(QStringList, mimetypes);
-+        QFETCH(QVector<qint64>, expectedResults);
-+
-+        QVector<qint64> results = SearchHelper::matchSubcollectionsByMimeType(ancestors, mimetypes);
-+
-+        qSort(expectedResults);
-+        qSort(results);
-+
-+        QCOMPARE(results.size(), expectedResults.size());
-+        QCOMPARE(results, expectedResults);
-+    }
-+
-+};
-+
-+AKTEST_FAKESERVER_MAIN(SearchTest)
-+
-+#include "searchtest.moc"
--- 
-2.1.4
-

-- 
Akonadi packaging



More information about the pkg-kde-commits mailing list