Hello community, here is the log from the commit of package akonadi-runtime for openSUSE:Factory checked in at 2014-08-25 10:58:18 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/akonadi-runtime (Old) and /work/SRC/openSUSE:Factory/.akonadi-runtime.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "akonadi-runtime" Changes: -------- --- /work/SRC/openSUSE:Factory/akonadi-runtime/akonadi-runtime.changes 2014-07-16 16:19:29.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.akonadi-runtime.new/akonadi-runtime.changes 2014-08-25 10:58:26.000000000 +0200 @@ -1,0 +2,11 @@ +Fri Aug 15 08:07:44 UTC 2014 - [email protected] + +- Update to 1.13.0 + * Fixed virtual collections statistics + * Fixed tag RID fetch + * Fixed HRID-based fetches + * Fixed race condition in StorageDebugger + * Use FindBacktrace.cmake from CMake 3.0 instead of our own + detection + +------------------------------------------------------------------- Old: ---- akonadi-1.12.91.tar.bz2 New: ---- akonadi-1.13.0.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ akonadi-runtime.spec ++++++ --- /var/tmp/diff_new_pack.7flabk/_old 2014-08-25 10:58:27.000000000 +0200 +++ /var/tmp/diff_new_pack.7flabk/_new 2014-08-25 10:58:27.000000000 +0200 @@ -17,7 +17,7 @@ Name: akonadi-runtime -Version: 1.12.91 +Version: 1.13.0 Release: 0 %define rname akonadi Summary: PIM Storage Service ++++++ akonadi-1.12.91.tar.bz2 -> akonadi-1.13.0.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/AUTHORS new/akonadi-1.13.0/AUTHORS --- old/akonadi-1.12.91/AUTHORS 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/AUTHORS 2014-08-10 12:38:58.000000000 +0200 @@ -82,6 +82,7 @@ - Timo Hummel <[email protected]> - Tom Albers <[email protected]> - Torgny Nyblom <[email protected]> +- Vadim Zhukov <[email protected]> - Will Stephenson <[email protected]> - Wolfgang Rohdewald <[email protected]> - Yury G. Kudryashov <[email protected]> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/CMakeLists.txt new/akonadi-1.13.0/CMakeLists.txt --- old/akonadi-1.12.91/CMakeLists.txt 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/CMakeLists.txt 2014-08-10 12:38:58.000000000 +0200 @@ -48,16 +48,16 @@ ############### The Akonadi version (used in AkonadiConfig.cmake) ############### -set(AKONADI_VERSION_PATCH "91") +set(AKONADI_VERSION_PATCH "0") # Raise the minor version if we're building Akonadi using Qt5 if(QT5_BUILD) set(AKONADI_VERSION_MAJOR "1") - set(AKONADI_VERSION_MINOR "78") + set(AKONADI_VERSION_MINOR "79") set(AKONADI_SOVERSION "2") else () set(AKONADI_VERSION_MAJOR "1") - set(AKONADI_VERSION_MINOR "12") + set(AKONADI_VERSION_MINOR "13") set(AKONADI_SOVERSION "1") endif() @@ -254,15 +254,10 @@ set(AKONADI_SYSTEM_LIBS) -check_include_files(execinfo.h HAVE_EXECINFO_H) -if(HAVE_EXECINFO_H) - check_function_exists(backtrace BACKTRACE_IN_LIBC) - if(NOT BACKTRACE_IN_LIBC) - find_library(EXECINFO_LIBRARY NAMES execinfo) - if(EXECINFO_LIBRARY) - set(AKONADI_SYSTEM_LIBS ${AKONADI_SYSTEM_LIBS} ${EXECINFO_LIBRARY}) - endif() - endif() +find_package(Backtrace) +if(Backtrace_FOUND) + include_directories(${Backtrace_INCLUDE_DIRS}) + set(AKONADI_SYSTEM_LIBS ${AKONADI_SYSTEM_LIBS} ${Backtrace_LIBRARIES}) endif() check_include_files(unistd.h HAVE_UNISTD_H) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/NEWS new/akonadi-1.13.0/NEWS --- old/akonadi-1.12.91/NEWS 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/NEWS 2014-08-10 12:38:58.000000000 +0200 @@ -1,3 +1,11 @@ +1.13.0 10-August-2014 +---------------------------------------------- +- Fixed virtual collections statistics +- Fixed tag RID fetch +- Fixed HRID-based fetches +- Fixed race condition in StorageDebugger +- Use FindBacktrace.cmake from CMake 3.0 instead of our own detection + 1.12.90 07-July-2014 ---------------------------------------------- - MERGE command for faster synchronization diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/cmake/modules/FindBacktrace.cmake new/akonadi-1.13.0/cmake/modules/FindBacktrace.cmake --- old/akonadi-1.12.91/cmake/modules/FindBacktrace.cmake 1970-01-01 01:00:00.000000000 +0100 +++ new/akonadi-1.13.0/cmake/modules/FindBacktrace.cmake 2014-08-10 12:38:58.000000000 +0200 @@ -0,0 +1,84 @@ +# - Find provider for backtrace(3) +# Checks if OS supports backtrace(3) via either libc or custom library. +# This module defines the following variables: +# Backtrace_HEADER - The header file needed for backtrace(3). Cached. +# Could be forcibly set by user. +# Backtrace_INCLUDE_DIRS - The include directories needed to use backtrace(3) header. +# Backtrace_LIBRARIES - The libraries (linker flags) needed to use backtrace(3), if any. +# Backtrace_FOUND - Is set if and only if backtrace(3) support detected. +# +# The following cache variables are also available to set or use: +# Backtrace_LIBRARY - The external library providing backtrace, if any. +# Backtrace_INCLUDE_DIR - The directory holding the backtrace(3) header. +# +# Typical usage is to generate of header file using configure_file() with the +# contents like the following: +# #cmakedefine01 Backtrace_FOUND +# #if Backtrace_FOUND +# # include <${Backtrace_HEADER}> +# #endif +# And then reference that generated header file in actual source. + +#============================================================================= +# Copyright (c) 2013, Vadim Zhukov <[email protected]> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +include(CMakePushCheckState) +include(CheckSymbolExists) +include(FindPackageHandleStandardArgs) + +# List of variables to be provided to find_package_handle_standard_args() +set(_Backtrace_STD_ARGS Backtrace_INCLUDE_DIR) + +if(Backtrace_HEADER) + set(_Backtrace_HEADER_TRY "${Backtrace_HEADER}") +else(Backtrace_HEADER) + set(_Backtrace_HEADER_TRY "execinfo.h") +endif(Backtrace_HEADER) + +find_path(Backtrace_INCLUDE_DIR "${_Backtrace_HEADER_TRY}") +set(Backtrace_INCLUDE_DIRS ${Backtrace_INCLUDE_DIR}) + +# First, check if we already have backtrace(), e.g., in libc +cmake_push_check_state(RESET) +set(CMAKE_REQUIRED_INCLUDES ${Backtrace_INCLUDE_DIRS}) +check_symbol_exists("backtrace" "${_Backtrace_HEADER_TRY}" _Backtrace_SYM_FOUND) +cmake_pop_check_state() + +if(_Backtrace_SYM_FOUND) + set(Backtrace_LIBRARY) + if(NOT Backtrace_FIND_QUIETLY) + message(STATUS "backtrace facility detected in default set of libraries") + endif() +else() + # Check for external library, for non-glibc systems + if(Backtrace_INCLUDE_DIR) + # OpenBSD has libbacktrace renamed to libexecinfo + find_library(Backtrace_LIBRARY "execinfo") + elseif() # respect user wishes + set(_Backtrace_HEADER_TRY "backtrace.h") + find_path(Backtrace_INCLUDE_DIR ${_Backtrace_HEADER_TRY}) + find_library(Backtrace_LIBRARY "backtrace") + endif() + + # Prepend list with library path as it's more common practice + set(_Backtrace_STD_ARGS Backtrace_LIBRARY ${_Backtrace_STD_ARGS}) +endif() + +set(Backtrace_LIBRARIES ${Backtrace_LIBRARY}) +set(Backtrace_HEADER "${_Backtrace_HEADER_TRY}" CACHE STRING "Header providing backtrace(3) facility") + +find_package_handle_standard_args(Backtrace FOUND_VAR Backtrace_FOUND REQUIRED_VARS ${_Backtrace_STD_ARGS}) +mark_as_advanced(Backtrace_HEADER Backtrace_INCLUDE_DIR Backtrace_LIBRARY) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/config-akonadi.h.cmake new/akonadi-1.13.0/config-akonadi.h.cmake --- old/akonadi-1.12.91/config-akonadi.h.cmake 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/config-akonadi.h.cmake 2014-08-10 12:38:58.000000000 +0200 @@ -1,4 +1,8 @@ -#cmakedefine HAVE_EXECINFO_H 1 +#cmakedefine01 Backtrace_FOUND +#if Backtrace_FOUND +# include <@Backtrace_HEADER@> +#endif + #cmakedefine HAVE_UNISTD_H 1 #cmakedefine HAVE_SOPRANO 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/server/src/connection.cpp new/akonadi-1.13.0/server/src/connection.cpp --- old/akonadi-1.12.91/server/src/connection.cpp 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/server/src/connection.cpp 2014-08-10 12:38:58.000000000 +0200 @@ -132,7 +132,7 @@ ClientCapabilityAggregator::removeSession( m_clientCapabilities ); Tracer::self()->endConnection( m_identifier, QString() ); - collectionReferenceManager()->removeSession( m_identifier.toLatin1() ); + collectionReferenceManager()->removeSession( m_sessionId ); } void Connection::slotNewData() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/server/src/handler/fetchhelper.cpp new/akonadi-1.13.0/server/src/handler/fetchhelper.cpp --- old/akonadi-1.12.91/server/src/handler/fetchhelper.cpp 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/server/src/handler/fetchhelper.cpp 2014-08-10 12:38:58.000000000 +0200 @@ -40,6 +40,7 @@ #include "intervalcheck.h" #include "agentmanagerinterface.h" #include "dbusconnectionpool.h" +#include "tagfetchhelper.h" #include <QtCore/QLocale> #include <QtCore/QStringList> @@ -213,6 +214,7 @@ Tag::idFullColumnName(), PimItemTagRelation::rightFullColumnName() ); tagQuery.addColumn( PimItem::idFullColumnName() ); tagQuery.addColumn( Tag::idFullColumnName() ); + ItemQueryHelper::scopeToQuery( mScope, mConnection->context(), tagQuery ); tagQuery.addSortColumn( PimItem::idFullColumnName(), Query::Descending ); @@ -294,6 +296,23 @@ return properties.value( QLatin1String( "HasLocalStorage" ), false ).toBool(); } +QByteArray FetchHelper::tagsToByteArray( const Tag::List &tags ) +{ + QByteArray b; + QList<QByteArray> attributes; + b += "("; + Q_FOREACH ( const Tag &tag, tags ) { + b += "(" + TagFetchHelper::tagToByteArray( tag.id(), + tag.gid().toLatin1(), + tag.parentId(), + tag.tagType().name().toLatin1(), + QByteArray(), + TagFetchHelper::fetchTagAttributes( tag.id() ) ) + ") "; + } + b += ")"; + return b; +} + bool FetchHelper::fetchItems( const QByteArray &responseIdentifier ) { // retrieve missing parts @@ -428,6 +447,9 @@ if ( mFetchScope.tagsRequested() ) { ImapSet tags; + QVector<qint64> tagIds; + //We don't take the fetch scope into account yet. It's either id only or the full tag. + const bool fullTagsRequested = !mFetchScope.tagFetchScope().isEmpty(); while ( tagQuery.isValid() ) { const qint64 id = tagQuery.value( TagQueryItemIdColumn ).toLongLong(); if ( id > pimItemId ) { @@ -438,10 +460,20 @@ } const qint64 tagId = tagQuery.value( TagQueryTagIdColumn ).toLongLong(); tags.add( QVector<qint64>() << tagId ); + + tagIds << tagId; tagQuery.next(); } - if ( !tags.isEmpty() ) { - attributes.append( AKONADI_PARAM_TAGS " " + tags.toImapSequenceSet() ); + if ( !fullTagsRequested ) { + if ( !tags.isEmpty() ) { + attributes.append( AKONADI_PARAM_TAGS " " + tags.toImapSequenceSet() ); + } + } else { + Tag::List tagList; + Q_FOREACH ( qint64 t, tagIds ) { + tagList << Tag::retrieveById( t ); + } + attributes.append( AKONADI_PARAM_TAGS " " + tagsToByteArray( tagList ) ); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/server/src/handler/fetchhelper.h new/akonadi-1.13.0/server/src/handler/fetchhelper.h --- old/akonadi-1.12.91/server/src/handler/fetchhelper.h 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/server/src/handler/fetchhelper.h 2014-08-10 12:38:58.000000000 +0200 @@ -76,6 +76,7 @@ static bool needsAccessTimeUpdate( const QVector<QByteArray> &parts ); QVariant extractQueryResult( const QSqlQuery &query, ItemQueryColumns column ) const; bool isScopeLocal( const Scope &scope ); + static QByteArray tagsToByteArray(const Tag::List &tags); private: ImapStreamParser *mStreamParser; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/server/src/handler/fetchscope.cpp new/akonadi-1.13.0/server/src/handler/fetchscope.cpp --- old/akonadi-1.12.91/server/src/handler/fetchscope.cpp 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/server/src/handler/fetchscope.cpp 2014-08-10 12:38:58.000000000 +0200 @@ -55,6 +55,7 @@ uint mGidRequested : 1; uint mTagsRequested : 1; uint mVirtRefRequested: 1; + QVector<QByteArray> mTagFetchScope; }; FetchScope::Private::Private() @@ -99,6 +100,7 @@ , mGidRequested( other.mGidRequested ) , mTagsRequested( other.mTagsRequested ) , mVirtRefRequested( other.mVirtRefRequested ) + , mTagFetchScope( other.mTagFetchScope ) { } @@ -167,6 +169,12 @@ mGidRequested = true; } else if ( b == AKONADI_PARAM_TAGS ) { mTagsRequested = true; + if (mStreamParser->hasList()) { + mStreamParser->beginList(); + while (!mStreamParser->atListEnd()) { + mTagFetchScope << mStreamParser->readString(); + } + } } else if ( b == AKONADI_PARAM_COLLECTIONID ) { // we always return collection IDs anyway } else if ( b == AKONADI_PARAM_VIRTREF ) { @@ -391,6 +399,11 @@ return d->mTagsRequested; } +QVector<QByteArray> FetchScope::tagFetchScope() const +{ + return d->mTagFetchScope; +} + void FetchScope::setVirtualReferencesRequested( bool vRefRequested ) { d->mVirtRefRequested = vRefRequested; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/server/src/handler/fetchscope.h new/akonadi-1.13.0/server/src/handler/fetchscope.h --- old/akonadi-1.12.91/server/src/handler/fetchscope.h 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/server/src/handler/fetchscope.h 2014-08-10 12:38:58.000000000 +0200 @@ -78,6 +78,7 @@ bool gidRequested() const; void setTagsRequested( bool tagsRequested ); bool tagsRequested() const; + QVector<QByteArray> tagFetchScope() const; void setVirtualReferencesRequested( bool vRefRequested ); bool virtualReferencesRequested() const; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/server/src/handler/merge.cpp new/akonadi-1.13.0/server/src/handler/merge.cpp --- old/akonadi-1.12.91/server/src/handler/merge.cpp 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/server/src/handler/merge.cpp 2014-08-10 12:38:58.000000000 +0200 @@ -53,7 +53,7 @@ const ChangedAttributes &itemTagsRID, const ChangedAttributes &itemTagsGID ) { - if ( !newItem.rev() > 0 ) { + if ( newItem.rev() > 0 ) { currentItem.setRev( newItem.rev() ); } if ( !newItem.remoteId().isEmpty() && currentItem.remoteId() != newItem.remoteId() ) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/server/src/handler/tagappend.cpp new/akonadi-1.13.0/server/src/handler/tagappend.cpp --- old/akonadi-1.12.91/server/src/handler/tagappend.cpp 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/server/src/handler/tagappend.cpp 2014-08-10 12:38:58.000000000 +0200 @@ -24,6 +24,7 @@ #include "response.h" #include "storage/datastore.h" #include "storage/querybuilder.h" +#include "storage/countquerybuilder.h" #include "entities.h" #include "libs/protocol_p.h" @@ -122,12 +123,33 @@ } if ( !remoteId.isEmpty() ) { - Resource resource = Resource::retrieveByName( connection()->context()->resource().name() ); - TagRemoteIdResourceRelation rel; - rel.setTagId( tagId ); - rel.setResourceId( resource.id() ); - rel.setRemoteId( remoteId ); - if ( !rel.insert() ) { + const qint64 resourceId = connection()->context()->resource().id(); + + CountQueryBuilder qb( TagRemoteIdResourceRelation::tableName() ); + qb.addValueCondition( TagRemoteIdResourceRelation::tagIdColumn(), Query::Equals, tagId ); + qb.addValueCondition( TagRemoteIdResourceRelation::resourceIdColumn(), Query::Equals, resourceId ); + if ( !qb.exec() ) { + throw HandlerException( "Failed to query for existing TagRemoteIdResourceRelation entries" ); + } + const bool exists = ( qb.result() > 0 ); + + //If the relation is already existing simply update it (can happen if a resource simply creates the tag again while enabling merge) + bool ret = false; + if ( exists ) { + //Simply using update() doesn't work since TagRemoteIdResourceRelation only takes the tagId for identification of the column + QueryBuilder qb( TagRemoteIdResourceRelation::tableName(), QueryBuilder::Update ); + qb.addValueCondition( TagRemoteIdResourceRelation::tagIdColumn(), Query::Equals, tagId ); + qb.addValueCondition( TagRemoteIdResourceRelation::resourceIdColumn(), Query::Equals, resourceId ); + qb.setColumnValue( TagRemoteIdResourceRelation::remoteIdColumn(), remoteId ); + ret = qb.exec(); + } else { + TagRemoteIdResourceRelation rel; + rel.setTagId( tagId ); + rel.setResourceId( resourceId ); + rel.setRemoteId( remoteId ); + ret = rel.insert(); + } + if ( !ret ) { throw HandlerException( "Failed to store tag remote ID" ); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/server/src/handler/tagfetchhelper.cpp new/akonadi-1.13.0/server/src/handler/tagfetchhelper.cpp --- old/akonadi-1.12.91/server/src/handler/tagfetchhelper.cpp 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/server/src/handler/tagfetchhelper.cpp 2014-08-10 12:38:58.000000000 +0200 @@ -38,7 +38,7 @@ { } -QSqlQuery TagFetchHelper::buildAttributeQuery() +QSqlQuery TagFetchHelper::buildAttributeQuery() const { QueryBuilder qb( TagAttribute::tableName() ); qb.addColumn( TagAttribute::tagIdColumn() ); @@ -56,6 +56,24 @@ return qb.query(); } +QSqlQuery TagFetchHelper::buildAttributeQuery( qint64 id ) +{ + QueryBuilder qb( TagAttribute::tableName() ); + qb.addColumn( TagAttribute::tagIdColumn() ); + qb.addColumn( TagAttribute::typeColumn() ); + qb.addColumn( TagAttribute::valueColumn() ); + qb.addSortColumn( TagAttribute::tagIdColumn(), Query::Descending ); + + qb.addValueCondition( TagAttribute::tagIdColumn(), Query::Equals, id ); + + if ( !qb.exec() ) { + throw HandlerException( "Unable to list tag attributes" ); + } + + qb.query().next(); + return qb.query(); +} + QSqlQuery TagFetchHelper::buildTagQuery() { QueryBuilder qb( Tag::tableName() ); @@ -68,17 +86,16 @@ // Expose tag's remote ID only to resources if ( mConnection->context()->resource().isValid() ) { qb.addColumn( TagRemoteIdResourceRelation::remoteIdFullColumnName() ); - qb.addJoin( QueryBuilder::LeftJoin, TagRemoteIdResourceRelation::tableName(), - Tag::idFullColumnName(), TagRemoteIdResourceRelation::tagIdFullColumnName() ); Query::Condition joinCondition; - joinCondition.addColumnCondition( Resource::idFullColumnName(), Query::Equals, TagRemoteIdResourceRelation::resourceIdFullColumnName() ); - joinCondition.addValueCondition( Resource::nameFullColumnName(), Query::Equals, mConnection->context()->resource().name() ); - qb.addJoin( QueryBuilder::LeftJoin, Resource::tableName(), joinCondition ); + joinCondition.addValueCondition( TagRemoteIdResourceRelation::resourceIdFullColumnName(), + Query::Equals, mConnection->context()->resource().id() ); + joinCondition.addColumnCondition( TagRemoteIdResourceRelation::tagIdFullColumnName(), + Query::Equals, Tag::idFullColumnName() ); + qb.addJoin( QueryBuilder::LeftJoin, TagRemoteIdResourceRelation::tableName(), joinCondition ); } qb.addSortColumn( Tag::idFullColumnName(), Query::Descending ); QueryHelper::setToQuery( mSet, Tag::idFullColumnName(), qb ); - if ( !qb.exec() ) { throw HandlerException( "Unable to list tags" ); } @@ -87,6 +104,36 @@ return qb.query(); } +QList<QByteArray> TagFetchHelper::fetchTagAttributes( qint64 tagId ) +{ + QList<QByteArray> attributes; + + QSqlQuery attributeQuery = buildAttributeQuery( tagId ); + while ( attributeQuery.isValid() ) { + const QByteArray attrName = attributeQuery.value( 1 ).toByteArray(); + const QByteArray attrValue = attributeQuery.value( 2 ).toByteArray(); + + attributes << attrName << ImapParser::quote( attrValue ); + attributeQuery.next(); + } + return attributes; +} + +QByteArray TagFetchHelper::tagToByteArray(qint64 tagId, const QByteArray &gid, qint64 parentId, const QByteArray &type, const QByteArray &remoteId, const QList<QByteArray> &tagAttributes) +{ + QList<QByteArray> attributes; + attributes << AKONADI_PARAM_UID << QByteArray::number( tagId ); + attributes << AKONADI_PARAM_GID << ImapParser::quote( gid ); + attributes << AKONADI_PARAM_PARENT << QByteArray::number( parentId ); + attributes << AKONADI_PARAM_MIMETYPE " " + ImapParser::quote( type ); + if ( !remoteId.isEmpty() ) { + attributes << AKONADI_PARAM_REMOTEID << remoteId; + } + + attributes << tagAttributes; + + return ImapParser::join( attributes, " " ); +} bool TagFetchHelper::fetchTags(const QByteArray& responseIdentifier) { @@ -107,15 +154,7 @@ remoteId = tagQuery.value( 5 ).toByteArray(); } - QList<QByteArray> attributes; - attributes << AKONADI_PARAM_UID << QByteArray::number( tagId ); - attributes << AKONADI_PARAM_GID << ImapParser::quote( gid ); - attributes << AKONADI_PARAM_PARENT << QByteArray::number( parentId ); - attributes << AKONADI_PARAM_MIMETYPE " " + ImapParser::quote( type ); - if ( !remoteId.isEmpty() ) { - attributes << AKONADI_PARAM_REMOTEID << remoteId; - } - + QList<QByteArray> tagAttributes; while ( attributeQuery.isValid() ) { const qint64 id = attributeQuery.value( 0 ).toLongLong(); if ( id > tagId ) { @@ -128,12 +167,11 @@ const QByteArray attrName = attributeQuery.value( 1 ).toByteArray(); const QByteArray attrValue = attributeQuery.value( 2 ).toByteArray(); - attributes << attrName << ImapParser::quote( attrValue ); + tagAttributes << attrName << ImapParser::quote( attrValue ); attributeQuery.next(); } - QByteArray tagReply = QByteArray::number( tagId ) + ' ' + responseIdentifier + " ("; - tagReply += ImapParser::join( attributes, " " ) + ')'; + tagReply += tagToByteArray(tagId, gid, parentId, type, remoteId, tagAttributes) + ')'; response.setUntagged(); response.setString( tagReply ); Q_EMIT responseAvailable( response ); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/server/src/handler/tagfetchhelper.h new/akonadi-1.13.0/server/src/handler/tagfetchhelper.h --- old/akonadi-1.12.91/server/src/handler/tagfetchhelper.h 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/server/src/handler/tagfetchhelper.h 2014-08-10 12:38:58.000000000 +0200 @@ -45,12 +45,16 @@ bool fetchTags( const QByteArray &responseIdentifier ); + static QList<QByteArray> fetchTagAttributes( qint64 tagId ); + static QByteArray tagToByteArray( qint64 tagId, const QByteArray &gid, qint64 parentId, const QByteArray &type, const QByteArray &remoteId, const QList<QByteArray> &tagAttributes ); + Q_SIGNALS: void responseAvailable( const Akonadi::Server::Response &response ); private: QSqlQuery buildTagQuery(); - QSqlQuery buildAttributeQuery(); + QSqlQuery buildAttributeQuery() const; + static QSqlQuery buildAttributeQuery( qint64 id ); private: ImapStreamParser *mStreamParser; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/server/src/storage/datastore.cpp new/akonadi-1.13.0/server/src/storage/datastore.cpp --- old/akonadi-1.12.91/server/src/storage/datastore.cpp 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/server/src/storage/datastore.cpp 2014-08-10 12:38:58.000000000 +0200 @@ -928,7 +928,7 @@ item.setRemoteRevision( query.value( 3 ).toString() ); item.setMimeTypeId( query.value( 4 ).toLongLong() ); pimItems << item; - } while (query.next() && query.value(0).toLongLong() > collectionId); + } while (query.next() && query.value(0).toLongLong() == collectionId); } return map; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/server/src/storage/itemqueryhelper.cpp new/akonadi-1.13.0/server/src/storage/itemqueryhelper.cpp --- old/akonadi-1.12.91/server/src/storage/itemqueryhelper.cpp 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/server/src/storage/itemqueryhelper.cpp 2014-08-10 12:38:58.000000000 +0200 @@ -122,6 +122,7 @@ const QString itemRid = ridChain.takeFirst(); const Collection parentCol = CollectionQueryHelper::resolveHierarchicalRID( ridChain, context->resource().id() ); const Collection oldSelection = context->collection(); + context->setCollection( parentCol ); remoteIdToQuery( QStringList() << itemRid, context, qb ); context->setCollection( oldSelection ); return; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/server/src/storage/storagedebugger.cpp new/akonadi-1.13.0/server/src/storage/storagedebugger.cpp --- old/akonadi-1.12.91/server/src/storage/storagedebugger.cpp 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/server/src/storage/storagedebugger.cpp 2014-08-10 12:38:58.000000000 +0200 @@ -66,14 +66,14 @@ void StorageDebugger::queryExecuted( const QSqlQuery &query, int duration ) { - mSequence++; + const qint64 seq = mSequence.fetchAndAddOrdered(1); if ( !mEnabled ) { return; } if ( query.lastError().isValid() ) { - Q_EMIT queryExecuted( mSequence, duration, query.executedQuery(), query.boundValues(), + Q_EMIT queryExecuted( seq, duration, query.executedQuery(), query.boundValues(), 0, QList< QList<QVariant> >(), query.lastError().text() ); return; } @@ -107,7 +107,7 @@ querySize = query.numRowsAffected(); } - Q_EMIT queryExecuted( mSequence, duration, query.executedQuery(), + Q_EMIT queryExecuted( seq, duration, query.executedQuery(), query.boundValues(), querySize, result, QString() ); // Reset the query diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/server/src/storage/storagedebugger.h new/akonadi-1.13.0/server/src/storage/storagedebugger.h --- old/akonadi-1.12.91/server/src/storage/storagedebugger.h 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/server/src/storage/storagedebugger.h 2014-08-10 12:38:58.000000000 +0200 @@ -25,6 +25,13 @@ #include <QtCore/QMap> #include <QtCore/QVariant> +#ifdef QT5_BUILD +#include <QAtomicInteger> +#else +#include <QAtomicInt> +#endif + + class QSqlQuery; namespace Akonadi { @@ -44,7 +51,7 @@ void queryExecuted( const QSqlQuery &query, int duration ); - void incSequence() { ++mSequence; } + void incSequence() { mSequence.ref(); } Q_SIGNALS: void queryExecuted( double sequence, uint duration, const QString &query, @@ -60,7 +67,11 @@ static QMutex mMutex; bool mEnabled; - double mSequence; +#ifdef Q_ATOMC_INT64_IS_SUPPORTED + QAtomicInteger<qint64> mSequence; +#else + QAtomicInt mSequence; +#endif }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/server/tests/unittest/akappendhandlertest.cpp new/akonadi-1.13.0/server/tests/unittest/akappendhandlertest.cpp --- old/akonadi-1.12.91/server/tests/unittest/akappendhandlertest.cpp 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/server/tests/unittest/akappendhandlertest.cpp 2014-08-10 12:38:58.000000000 +0200 @@ -431,7 +431,7 @@ updatePimItem(pimItem, QLatin1String("TEST-14"), 0); updateParts(parts, {}); - updateFlags(flags, { QLatin1String("\\SEEN"), QLatin1String("\\RANDOM") }); + updateFlags(flags, QStringList() << QLatin1String("\\SEEN") << QLatin1String("\\RANDOM") ); updateNotifcationEntity(notification, pimItem); ++uidnext; scenario.clear(); @@ -504,7 +504,7 @@ updatePimItem(pimItem, QLatin1String("TEST-19"), 0); - updateFlags(flags, { QLatin1String("\\SEEN"), QLatin1String("$FLAG") } ); + updateFlags(flags, QStringList() << QLatin1String("\\SEEN") << QLatin1String("$FLAG") ); updateTags(tags, { { QLatin1String("PLAIN"), QLatin1String("TAG-1") }, { QLatin1String("PLAIN"), QLatin1String("TAG-2") } }); updateNotifcationEntity(notification, pimItem); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/server/tests/unittest/collectionreferencetest.cpp new/akonadi-1.13.0/server/tests/unittest/collectionreferencetest.cpp --- old/akonadi-1.12.91/server/tests/unittest/collectionreferencetest.cpp 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/server/tests/unittest/collectionreferencetest.cpp 2014-08-10 12:38:58.000000000 +0200 @@ -127,7 +127,6 @@ { QTest::addColumn<QList<QByteArray> >("scenario"); QTest::addColumn<QList<Akonadi::NotificationMessageV3> >("expectedNotifications"); - QTest::addColumn<Collection::List>("expectedCollections"); Akonadi::NotificationMessageV3 notificationTemplate; notificationTemplate.setType(NotificationMessageV2::Collections); @@ -139,10 +138,10 @@ { QList<QByteArray> scenario; scenario << FakeAkonadiServer::defaultScenario() - << "C: 2 LIST 0 1 (RESOURCE \"testresource\" ENABLED TRUE) ()" + << "C: 2 LIST 0 INF (RESOURCE \"testresource\" ENABLED TRUE) ()" << initializer.listResponse(initializer.collection("col1")) << "S: 2 OK List completed"; - QTest::newRow("list before referenced first level") << scenario << QList<Akonadi::NotificationMessageV3>() << Collection::List(); + QTest::newRow("list before referenced first level") << scenario << QList<Akonadi::NotificationMessageV3>(); } { @@ -154,46 +153,54 @@ Akonadi::NotificationMessageV3 notification = notificationTemplate; notification.setItemParts(QSet<QByteArray>() << "REFERENCED"); - Collection col = initializer.collection("col2"); - col.setReferenced(true); - - QTest::newRow("reference") << scenario << (QList<Akonadi::NotificationMessageV3>() << notification) << (Collection::List() << col); + QTest::newRow("reference") << scenario << (QList<Akonadi::NotificationMessageV3>() << notification); } + { Collection col2 = initializer.collection("col2"); col2.setReferenced(true); QList<QByteArray> scenario; scenario << FakeAkonadiServer::defaultScenario() - << "C: 2 LIST " + QByteArray::number(col2.id()) + " 0 (ENABLED TRUE) ()" + << "C: 2 MODIFY " + QByteArray::number(initializer.collection("col2").id()) + " REFERENCED TRUE" + << "S: 2 OK MODIFY done" + << "C: 3 LIST " + QByteArray::number(col2.id()) + " 0 (ENABLED TRUE) ()" << initializer.listResponse(col2) - << "S: 2 OK List completed"; + << "S: 3 OK List completed"; + + Akonadi::NotificationMessageV3 notification = notificationTemplate; + notification.setItemParts(QSet<QByteArray>() << "REFERENCED"); - QTest::newRow("list referenced base") << scenario << QList<Akonadi::NotificationMessageV3>() << Collection::List(); + QTest::newRow("list referenced base") << scenario << (QList<Akonadi::NotificationMessageV3>() << notification); } { Collection col2 = initializer.collection("col2"); col2.setReferenced(true); QList<QByteArray> scenario; scenario << FakeAkonadiServer::defaultScenario() - << "C: 2 LIST 0 1 (RESOURCE \"testresource\" ENABLED TRUE) ()" + << "C: 2 MODIFY " + QByteArray::number(initializer.collection("col2").id()) + " REFERENCED TRUE" + << "S: 2 OK MODIFY done" + << "C: 3 LIST 0 1 (RESOURCE \"testresource\" ENABLED TRUE) ()" << initializer.listResponse(initializer.collection("col1")) << initializer.listResponse(col2) - << "S: 2 OK List completed"; - QTest::newRow("list referenced first level") << scenario << QList<Akonadi::NotificationMessageV3>() << Collection::List(); + << "S: 3 OK List completed"; + + Akonadi::NotificationMessageV3 notification = notificationTemplate; + notification.setItemParts(QSet<QByteArray>() << "REFERENCED"); + + QTest::newRow("list referenced first level") << scenario << (QList<Akonadi::NotificationMessageV3>() << notification); } { QList<QByteArray> scenario; scenario << FakeAkonadiServer::defaultScenario() - << "C: 2 MODIFY " + QByteArray::number(initializer.collection("col2").id()) + " REFERENCED FALSE" - << "S: 2 OK MODIFY done"; + << "C: 2 MODIFY " + QByteArray::number(initializer.collection("col2").id()) + " REFERENCED TRUE" + << "S: 2 OK MODIFY done" + << "C: 3 MODIFY " + QByteArray::number(initializer.collection("col2").id()) + " REFERENCED FALSE" + << "S: 3 OK MODIFY done"; Akonadi::NotificationMessageV3 notification = notificationTemplate; notification.setItemParts(QSet<QByteArray>() << "REFERENCED"); - Collection col = initializer.collection("col2"); - col.setReferenced(false); - - QTest::newRow("dereference") << scenario << (QList<Akonadi::NotificationMessageV3>() << notification) << (Collection::List() << col); + QTest::newRow("dereference") << scenario << (QList<Akonadi::NotificationMessageV3>() << notification << notification); } } @@ -201,7 +208,6 @@ { QFETCH(QList<QByteArray>, scenario); QFETCH(QList<NotificationMessageV3>, expectedNotifications); - QFETCH(Collection::List, expectedCollections); FakeAkonadiServer::instance()->setScenario(scenario); FakeAkonadiServer::instance()->runTest(); @@ -210,22 +216,20 @@ if (expectedNotifications.isEmpty()) { QVERIFY(notificationSpy->isEmpty() || notificationSpy->takeFirst().first().value<NotificationMessageV3::List>().isEmpty()); } else { - QCOMPARE(notificationSpy->count(), 1); - //Only one notify call - QCOMPARE(notificationSpy->first().count(), 1); - const NotificationMessageV3::List receivedNotifications = notificationSpy->first().first().value<NotificationMessageV3::List>(); + NotificationMessageV3::List receivedNotifications; + for (int q = 0; q < notificationSpy->size(); q++) { + //Only one notify call + QCOMPARE(notificationSpy->first().count(), 1); + const NotificationMessageV3::List n = notificationSpy->first().first().value<NotificationMessageV3::List>(); + for (int i = 0; i < n.size(); i++) { + receivedNotifications.append(n.at(i)); + } + } QCOMPARE(receivedNotifications.size(), expectedNotifications.count()); - for (int i = 0; i < expectedNotifications.size(); i++) { QCOMPARE(receivedNotifications.at(i), expectedNotifications.at(i)); } } - - Q_FOREACH (const Collection &expected, expectedCollections) { - const Collection actual = Collection::retrieveByName(expected.name()); - QCOMPARE(actual.referenced(), expected.referenced()); - QCOMPARE(CollectionReferenceManager::instance()->isReferenced(actual.id()), expected.referenced()); - } } void testReferenceCollection() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/server/tests/unittest/imapstreamparsertest.cpp new/akonadi-1.13.0/server/tests/unittest/imapstreamparsertest.cpp --- old/akonadi-1.12.91/server/tests/unittest/imapstreamparsertest.cpp 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/server/tests/unittest/imapstreamparsertest.cpp 2014-08-10 12:38:58.000000000 +0200 @@ -26,6 +26,7 @@ #include "imapstreamparser.h" #include <aktest.h> +#include <config-akonadi.h> Q_DECLARE_METATYPE( QList<QByteArray> ) Q_DECLARE_METATYPE( QList<int> ) @@ -39,7 +40,7 @@ QString s; /* FIXME: is there an equivalent for darwin, *BSD, or windows? */ -#ifdef HAVE_EXECINFO_H +#ifdef Backtrace_FOUND void *trace[256]; int n = backtrace( trace, 256 ); if ( !n ) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-1.12.91/shared/akcrash.cpp new/akonadi-1.13.0/shared/akcrash.cpp --- old/akonadi-1.12.91/shared/akcrash.cpp 2014-07-09 22:14:29.000000000 +0200 +++ new/akonadi-1.13.0/shared/akcrash.cpp 2014-08-10 12:38:58.000000000 +0200 @@ -33,16 +33,13 @@ #ifdef HAVE_UNISTD_H # include <unistd.h> #endif -#ifdef HAVE_EXECINFO_H -# include <execinfo.h> -#endif QString akBacktrace() { QString s; -/* FIXME: is there an equivalent for darwin, *BSD, or windows? */ -#ifdef HAVE_EXECINFO_H +/* FIXME: is there an equivalent for windows? */ +#ifdef Backtrace_FOUND void *trace[256]; int n = backtrace( trace, 256 ); if ( !n ) { -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
