mpserviceplugins/mpxsqlitedbhgplugin/src/mpxdbcategory.cpp
changeset 22 ecf06a08d4d9
child 25 3ec52facab4d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mpserviceplugins/mpxsqlitedbhgplugin/src/mpxdbcategory.cpp	Mon May 03 12:29:20 2010 +0300
@@ -0,0 +1,708 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Responsible for interation with the category tables:
+*                Artist, Album, Genre and Composer
+*
+*/
+
+
+// INCLUDE FILES
+#include <sqldb.h>
+
+#include <mpxlog.h>
+
+#include "mpxdbcommonutil.h"
+#include "mpxdbcommondef.h"
+#include "mpxdbmanager.h"
+
+#include "mpxcollectiondbdef.h"
+#include "mpxdbpluginqueries.h"
+#include "mpxdbutil.h"
+#include "mpxdbcategory.h"
+
+// CONSTANTS
+
+// maximum number of table name entries per query
+const TInt KMaxTableNameCount = 2;
+
+// ============================ MEMBER FUNCTIONS ==============================
+
+
+// ----------------------------------------------------------------------------
+// Destructor
+// ----------------------------------------------------------------------------
+//
+CMPXDbCategory::~CMPXDbCategory()
+    {
+    MPX_FUNC("CMPXDbCategory::~CMPXDbCategory");
+    delete iTableName;
+    }
+
+// ----------------------------------------------------------------------------
+// Constructor
+// ----------------------------------------------------------------------------
+//
+CMPXDbCategory::CMPXDbCategory(
+    CMPXDbManager& aDbManager,
+    TMPXGeneralCategory aCategory) :
+    CMPXDbTable(aDbManager),
+    iCategory(aCategory)
+    {
+    MPX_FUNC("CMPXDbCategory::CMPXDbCategory");
+    }
+
+// ----------------------------------------------------------------------------
+// Second phase constructor.
+// ----------------------------------------------------------------------------
+//
+void CMPXDbCategory::BaseConstructL()
+    {
+    MPX_FUNC("CMPXDbCategory::BaseConstructL");
+
+    CMPXDbTable::BaseConstructL();
+    iTableName = MPXDbUtil::TableNameForCategoryL(iCategory).AllocL();
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbCategory::AddItemL
+// ----------------------------------------------------------------------------
+//
+TUint32 CMPXDbCategory::AddItemL(
+    const TDesC& aName,
+    TInt aDriveId,
+    TBool& aNewRecord,
+    TBool aCaseSensitive)
+    {
+    MPX_FUNC("CMPXDbCategory::AddItemL");
+
+    // try to find the item first
+    TUint32 rowId(MPXDbCommonUtil::GenerateUniqueIdL(iDbManager.Fs(), iCategory,
+        aName, aCaseSensitive));
+    aNewRecord = !CategoryItemExistsL(aDriveId, rowId);
+
+    if (aNewRecord)
+        {
+        // insert new
+        HBufC* query = PreProcessStringLC(KQueryCategoryInsert);
+        HBufC* name = MPXDbCommonUtil::ProcessSingleQuotesLC(aName);
+
+        iDbManager.ExecuteQueryL(aDriveId, *query, rowId, name, 1);
+
+        CleanupStack::PopAndDestroy(name);
+        CleanupStack::PopAndDestroy(query);
+        }
+    else
+        {
+        // increment the number of songs for the category
+        HBufC* query = PreProcessStringLC(KQueryCategoryIncrementSongCount);
+        iDbManager.ExecuteQueryL(aDriveId, *query, rowId);
+        CleanupStack::PopAndDestroy(query);
+        }
+
+    return rowId;
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbCategory::GetNameL
+// ----------------------------------------------------------------------------
+//
+HBufC* CMPXDbCategory::GetNameL(
+    TUint32 aId)
+    {
+    MPX_FUNC("CMPXDbCategory::GetNameL");
+
+    RSqlStatement recordset(GetCategoryRecordL(aId));
+    CleanupClosePushL(recordset);
+
+    if (recordset.Next() != KSqlAtRow)
+        {
+        User::LeaveIfError(KErrNotFound);
+        }
+
+    HBufC* name = MPXDbCommonUtil::GetColumnTextL(recordset, ECategoryName).AllocL();
+    CleanupStack::PopAndDestroy(&recordset);
+
+    return name;
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbCategory::CountL
+// ----------------------------------------------------------------------------
+//
+TInt CMPXDbCategory::CountL()
+    {
+    MPX_FUNC("CMPXDbCategory::CountL");
+
+    HBufC* query = PreProcessStringLC(KQueryCategoryCount);
+    TInt count(ExecuteSumQueryL(*query));
+    CleanupStack::PopAndDestroy(query);
+
+    return count;
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbCategory::FindAllL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbCategory::FindAllL(
+    const CMPXMedia& aCriteria,
+    const TArray<TMPXAttribute>& aAttrs,
+    CMPXMediaArray& aMediaArray)
+    {
+    MPX_FUNC("CMPXDbCategory::FindAllL");
+
+    TMPXGeneralType type = aCriteria.ValueTObjectL<TMPXGeneralType>(KMPXMediaGeneralType);
+
+    const TArray<TMPXAttribute> criteria = aCriteria.Attributes();
+    TInt criteriaCount(criteria.Count());
+
+    // process the criteria and construct the criteria string
+    CDesCArrayFlat* criteriaArray = new (ELeave) CDesCArrayFlat(criteriaCount + 1);
+    CleanupStack::PushL(criteriaArray);
+
+    for (TInt i = 0; i < criteriaCount; ++i)
+        {
+        const TMPXAttribute& criterion = criteria[i];
+        if ((type == EMPXItem) && (criterion == KMPXMediaGeneralId))
+            {
+            TUint32 itemId = (aCriteria.ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId)).iId2;
+            if (MPX_ITEM_CATEGORY(itemId) != iCategory)
+                {
+                User::Leave(KErrNotSupported);
+                }
+
+            HBufC* critStr = PreProcessStringLC(KCriterionCategoryUniqueId);
+            MPXDbCommonUtil::AddSqlCriterionL(*criteriaArray, *critStr, itemId);
+            CleanupStack::PopAndDestroy(critStr);
+            }
+        else if (criterion == KMPXMediaGeneralTitle)
+            {
+#ifdef RD_MPX_COLLECTION_CACHE
+           
+            if (aCriteria.ValueText(KMPXMediaGeneralTitle).Length() <= 0)
+                {
+                TUint32 itemId = MPXDbCommonUtil::GenerateUniqueIdL(
+                                    iDbManager.Fs(), iCategory, KNullDesC, EFalse);
+                HBufC* critStr = PreProcessStringLC(KCriterionCategoryUniqueId);
+                MPXDbCommonUtil::AddSqlCriterionL(*criteriaArray, *critStr, itemId);
+                CleanupStack::PopAndDestroy(critStr);
+                }
+            else
+                {
+
+#endif //RD_MPX_COLLECTION_CACHE
+                HBufC* critStr = PreProcessStringLC(KCriterionCategoryName);
+                HBufC* title = MPXDbCommonUtil::ProcessPatternCharsLC(
+                    aCriteria.ValueText(KMPXMediaGeneralTitle));
+                MPXDbCommonUtil::AddSqlCriterionL(*criteriaArray, *critStr, *title);
+                CleanupStack::PopAndDestroy(2, critStr); // title & critStr
+#ifdef RD_MPX_COLLECTION_CACHE
+                }
+#endif //RD_MPX_COLLECTION_CACHE
+            }
+#ifdef ABSTRACTAUDIOALBUM_INCLUDED
+          else if (criterion == KMPXMediaGeneralUri)
+                 {  
+                 TUint32 itemId(MPXDbCommonUtil::GenerateUniqueIdL(iDbManager.Fs(), iCategory,
+                       aCriteria.ValueText(KMPXMediaGeneralUri), (iCategory != EMPXGenre)));   
+                   HBufC* critStr = PreProcessStringLC(KCriterionCategoryUniqueId);
+                   MPXDbCommonUtil::AddSqlCriterionL(*criteriaArray, *critStr, itemId);
+             CleanupStack::PopAndDestroy(critStr);
+             }
+        else if (criterion == KMPXMediaGeneralDrive)
+            {
+            const TDesC& drive(aCriteria.ValueText(KMPXMediaGeneralDrive));
+            TDriveUnit driveUnit(drive);
+            MPXDbCommonUtil::AddSqlCriterionL(*criteriaArray, KCriterionAbstractAlbumVolumeId,
+                MPXDbCommonUtil::GetVolIdMatchDriveIdL(iDbManager.Fs(), driveUnit));
+            }
+#endif // ABSTRACTAUDIOALBUM_INCLUDED
+        else
+            {
+            // ignore attribute
+            }
+        }
+
+    // construct criteria string
+    HBufC* criteriaStr = MPXDbCommonUtil::StringFromArrayLC(*criteriaArray, KMCAndKeyword);
+
+    // either get all items or items filtered based on criteria
+    HBufC* query = PreProcessStringLC(criteriaStr->Length() ?
+        KQueryCategoryItems() : KQueryCategoryAll());
+    RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(*query, criteriaStr));
+    CleanupStack::PopAndDestroy(3, criteriaArray); // query, criteriaStr, criteriaArray
+    CleanupClosePushL(recordset);
+
+    // process the results
+    ProcessRecordsetL(aAttrs, recordset, aMediaArray);
+    CleanupStack::PopAndDestroy(&recordset);
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbCategory::DecrementSongsForCategoryL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbCategory::DecrementSongsForCategoryL(
+    const TUint32 aId,
+    TInt aDriveId,
+    CMPXMessageArray* aItemChangedMessages,
+    TBool& aItemExist,
+    TBool /*aMTPInUse*/)
+    {
+    MPX_FUNC("CMPXDbCategory::DecrementSongsForCategoryL");
+
+    // if just one song uses this category. Use <= just in case
+    if (GetSongsCountL(aDriveId, aId) <= 1)
+        {
+        aItemExist = EFalse;
+        // delete the category
+        DeleteCategoryL(aId, aDriveId);
+
+        if (aItemChangedMessages)
+            {
+            // add the item changed message
+            MPXDbCommonUtil::AddItemChangedMessageL(*aItemChangedMessages, aId, EMPXItemDeleted,
+                iCategory, KDBPluginUid);
+            }
+        }
+    else
+        {
+        aItemExist = ETrue;
+        // decrement the number of songs for the category
+        HBufC* query = PreProcessStringLC(KQueryCategoryDecrementSongCount);
+        iDbManager.ExecuteQueryL(aDriveId, *query, aId);
+        CleanupStack::PopAndDestroy(query);
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbCategory::DeleteCategoryL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbCategory::DeleteCategoryL(
+    TUint32 aId,
+    TInt aDriveId)
+    {
+    MPX_FUNC("CMPXDbCategory::DeleteCategoryL");
+
+    HBufC* query = PreProcessStringLC(KQueryCategoryDelete);
+    iDbManager.ExecuteQueryL(aDriveId, *query, aId);
+    CleanupStack::PopAndDestroy(query);
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbCategory::GetCategoryItemsL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbCategory::GetCategoryItemsL(
+    const TArray<TMPXAttribute>& aAttrs,
+    CMPXMediaArray& aMediaArray)
+    {
+    MPX_FUNC("CMPXDbCategory::GetCategoryItemsL");
+
+    // have to run one query to get all items as opposed to individual queries
+    // because of the sorting
+
+    // construct the unique ID criteria string
+    // (UniqueId = %u OR UniqueId = %u ...)
+    TInt count(aMediaArray.Count());
+    HBufC* criteria = HBufC::NewLC((2 * KCriterionCategoryUniqueId().Length() +
+        KMCIntegerLen + KMCOrKeyword().Length() + 2) * count);
+    TPtr ptr(criteria->Des());
+    ptr.Append(KMCOpenBracket);
+    for (TInt index = 0; index < count; ++index)
+        {
+        CMPXMedia* media = aMediaArray[index];
+
+        HBufC* critStr = PreProcessStringLC(KCriterionCategoryUniqueId);
+        HBufC* criterion = MPXDbCommonUtil::SqlCriterionLC(*critStr,
+            (media->ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId)).iId1);
+        ptr.Append(*criterion);
+        CleanupStack::PopAndDestroy(criterion);
+        CleanupStack::PopAndDestroy(critStr);
+
+        if (index < (count - 1))
+            {
+            ptr.Append(KMCOrKeyword);
+            }
+        }
+    ptr.Append(KMCCloseBracket);
+
+    // the array has to be reset as the items have to be returned in a different sort order
+    aMediaArray.Reset();
+
+    HBufC* query = PreProcessStringLC(KQueryCategoryItems);
+    RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(*query, criteria));
+
+    CleanupStack::PopAndDestroy(query);
+    CleanupStack::PopAndDestroy(criteria);
+
+    CleanupClosePushL(recordset);
+    ProcessRecordsetL(aAttrs, recordset, aMediaArray);
+    CleanupStack::PopAndDestroy(&recordset);
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbCategory::GetAllCategoryItemsL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbCategory::GetAllCategoryItemsL(
+    const TArray<TMPXAttribute>& aAttrs,
+    CMPXMediaArray& aMediaArray)
+    {
+    MPX_FUNC("CMPXDbCategory::GetAllCategoryItemsL");
+
+    HBufC* query = PreProcessStringLC(KQueryCategoryAll);
+    RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(*query));
+    CleanupStack::PopAndDestroy(query);
+
+    CleanupClosePushL(recordset);
+    ProcessRecordsetL(aAttrs, recordset, aMediaArray);
+    CleanupStack::PopAndDestroy(&recordset);
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbCategory::GetCategoryItemL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbCategory::GetCategoryItemL(
+    TUint32 aId,
+    const TArray<TMPXAttribute>& aAttrs,
+    CMPXMedia& aMedia)
+    {
+    MPX_FUNC("CMPXDbCategory::GetCategoryItemL");
+
+    HBufC* query = PreProcessStringLC(KQueryCategoryItem);
+    ExecuteMediaQueryL(aAttrs, aMedia, *query, aId);
+    CleanupStack::PopAndDestroy(query);
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbCategory::GetSubCategoryItemsL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbCategory::GetSubCategoryItemsL(
+    TMPXGeneralCategory aParentCategory,
+    TUint32 aParentId,
+    const TArray<TMPXAttribute>& aAttrs,
+    CMPXMediaArray& aMediaArray)
+    {
+    MPX_FUNC("CMPXDbCategory::GetSubCategoryItemsL");
+
+    // this is only valid for albums belonging to an artist
+    ASSERT((iCategory == EMPXAlbum) && (aParentCategory == EMPXArtist));
+
+    // to handle the UREL warning
+    (void)aParentCategory;
+
+    RSqlStatement recordset(iDbManager.ExecuteSelectQueryL(KQueryCategorySubcategoryItems, aParentId));
+    CleanupClosePushL(recordset);
+    ProcessRecordsetL(aAttrs, recordset, aMediaArray);
+    CleanupStack::PopAndDestroy(&recordset);
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbCategory::CategoryItemExistsL
+// The category records must be in the same database as the corresponding
+// Music record, otherwise when adding a duplicate of a song on a
+// different drive this method will return true and the category record won't
+// be created.
+// ----------------------------------------------------------------------------
+//
+TBool CMPXDbCategory::CategoryItemExistsL(
+    TInt aDriveId,
+    TUint32 aId)
+    {
+    MPX_FUNC("CMPXDbCategory::CategoryItemExistsL");
+
+    HBufC* query = PreProcessStringLC(KQueryCategoryItem);
+    RSqlStatement recordset(
+        iDbManager.ExecuteSelectQueryL(aDriveId, *query, aId));
+
+    TBool exists(recordset.Next() == KSqlAtRow);
+
+    recordset.Close();
+    CleanupStack::PopAndDestroy(query);
+
+    return exists;
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbCategory::GetSongsCountL
+// ----------------------------------------------------------------------------
+//
+TInt CMPXDbCategory::GetSongsCountL(
+    TInt aDriveId,
+    TUint32 aId)
+    {
+    MPX_FUNC("CMPXDbCategory::GetSongsCountL");
+
+    HBufC* query = PreProcessStringLC(KQueryCategoryGetSongCount);
+    RSqlStatement recordset(
+        iDbManager.ExecuteSelectQueryL(aDriveId, *query, aId));
+    CleanupClosePushL(recordset);
+
+    TInt err(KErrNone);
+    TInt ret(0);
+    while ((err = recordset.Next()) == KSqlAtRow)
+        {
+        ret += recordset.ColumnInt(KMPXTableDefaultIndex);
+        }
+
+    if (err != KSqlAtEnd)
+        {
+        User::Leave(err);
+        }
+
+    CleanupStack::PopAndDestroy(&recordset);
+    CleanupStack::PopAndDestroy(query);
+
+    return ret;
+    }
+
+void CMPXDbCategory::UpdateItemL(
+    TUint32 /*aId*/, 
+    const CMPXMedia& /*aMedia*/, 
+    TInt /*aDriveId*/, 
+    CMPXMessageArray* /*aItemChangedMessages*/)
+	{
+	// nothing
+	}
+
+// ----------------------------------------------------------------------------
+// CMPXDbCategory::UpdateMediaL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbCategory::UpdateMediaL(
+    RSqlStatement& aRecord,
+    const TArray<TMPXAttribute>& aAttrs,
+    CMPXMedia& aMedia)
+    {
+    MPX_FUNC("CMPXDbCategory::UpdateMediaL");
+
+    TInt count(aAttrs.Count());
+    for (TInt i = 0; i < count; ++i)
+        {
+        TInt contentId(aAttrs[i].ContentId());
+        TUint attributeId(aAttrs[i].AttributeId());
+
+        if (contentId == KMPXMediaIdGeneral)
+            {
+            if (attributeId & EMPXMediaGeneralId)
+                {
+                aMedia.SetTObjectValueL<TMPXItemId>(KMPXMediaGeneralId,
+                    aRecord.ColumnInt64(ECategoryUniqueId));
+                }
+            if (attributeId & EMPXMediaGeneralTitle)
+                {
+                aMedia.SetTextValueL(KMPXMediaGeneralTitle,
+                    MPXDbCommonUtil::GetColumnTextL(aRecord, ECategoryName));
+                }
+            if (attributeId & EMPXMediaGeneralCount)
+                {
+                aMedia.SetTObjectValueL<TInt>(KMPXMediaGeneralCount,
+                    GetSongsCountL(KDbManagerAllDrives,
+                    aRecord.ColumnInt64(ECategoryUniqueId)));
+                }
+            } // end if contentId == KMPXMediaIdGeneral
+        } // end for
+
+    aMedia.SetTObjectValueL<TMPXGeneralType>(KMPXMediaGeneralType, EMPXItem);
+    aMedia.SetTObjectValueL<TMPXGeneralCategory>(KMPXMediaGeneralCategory, iCategory);
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbCategory::GetCategoryRecordL
+// ----------------------------------------------------------------------------
+//
+RSqlStatement CMPXDbCategory::GetCategoryRecordL(
+    TUint32 aId)
+    {
+    MPX_FUNC("CMPXDbCategory::GetCategoryRecordL");
+    HBufC* query = PreProcessStringLC(KQueryCategoryItem);
+    RSqlStatement statement(iDbManager.ExecuteSelectQueryL(*query, aId));
+    CleanupStack::PopAndDestroy(query);
+
+    return statement;
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbCategory::PreProcessStringLC
+// ----------------------------------------------------------------------------
+//
+HBufC* CMPXDbCategory::PreProcessStringLC(
+    const TDesC& aQuery)
+    {
+    MPX_FUNC("CMPXDbCategory::PreProcessStringLC");
+
+    HBufC* query = HBufC::NewLC(aQuery.Length() + KMaxTableNameCount * (iTableName->Length() +
+        KCategoryTablePlaceholder().Length()));
+    TPtr queryPtr(query->Des());
+
+    // copy the query string
+    queryPtr = aQuery;
+
+    // replace all instances of the placeholder with the actual table name
+    TInt index(0);
+    while ((index = queryPtr.Find(KCategoryTablePlaceholder)) != KErrNotFound)
+        {
+        queryPtr.Replace(index, KCategoryTablePlaceholder().Length(), *iTableName);
+        }
+
+    return query;
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbCategory::ProcessRecordsetL
+// Unknown item is stored in the database as NULL (name field). This ensures the
+// unknown item to be the 1st found record if it exists. This will save time in
+// searching for the unknown record among the results and avoid performing
+// descriptor comparison. If the 1st record is the unknown item, it won't be
+// appended to the array until all other records have been put in the array.
+//
+// NOTE: putting unknown item to the end of the array only takes place when title
+//       field is requested. normal sorting algorithm occurs if title isn't
+//       requested.
+// ----------------------------------------------------------------------------
+//
+void CMPXDbCategory::ProcessRecordsetL(
+    const TArray<TMPXAttribute>& aAttrs,
+    RSqlStatement& aRecordset,
+    CMPXMediaArray& aMediaArray)
+    {
+    // populate the array
+    TBool firstRecord(ETrue);
+    CMPXMedia* unknownMedia(NULL);
+    TInt prevId(0);
+    TInt err(KErrNone);
+
+    TInt pPath(0);
+    if (aMediaArray.Count())
+        {
+        CMPXMedia* pMedia = aMediaArray[0];
+        if (pMedia->IsSupported(KMPXMediaGeneralValue))
+            { // Query excuted by OpenL
+            pPath = pMedia->ValueTObjectL<TInt>(KMPXMediaGeneralValue);
+            MPX_ASSERT(pPath);
+            }
+        }
+    RArray<TMPXItemId> ids;
+    CleanupClosePushL(ids);
+
+    while ((err = aRecordset.Next()) == KSqlAtRow)
+        {
+        TUint32 rowId(aRecordset.ColumnInt64(ECategoryUniqueId));
+        if (prevId == rowId)
+            {
+            continue;
+            }
+
+        prevId = rowId;
+        CMPXMedia* media = CMPXMedia::NewL();
+        CleanupStack::PushL(media);
+
+        UpdateMediaL(aRecordset, aAttrs, *media);
+
+        if (firstRecord &&
+            (MPXDbCommonUtil::GetColumnTextL(aRecordset, ECategoryName).Length() == 0))
+            {
+            unknownMedia = media;
+            }
+
+        if (!firstRecord || !unknownMedia)
+            {
+            if (media->IsSupported(KMPXMediaGeneralId) && pPath)
+                {
+                ids.AppendL(media->ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId));
+                }
+            aMediaArray.AppendL(*media);
+            CleanupStack::PopAndDestroy(media);
+            }
+
+        firstRecord = EFalse;
+        } // end while
+
+    if (err != KSqlAtEnd)
+        {
+        User::LeaveIfError(err);
+        }
+
+    if (unknownMedia)
+        {
+        if (unknownMedia->IsSupported(KMPXMediaGeneralId) && pPath)
+            {
+            ids.AppendL(unknownMedia->ValueTObjectL<TMPXItemId>(KMPXMediaGeneralId));
+            }
+        aMediaArray.AppendL(*unknownMedia);
+        CleanupStack::PopAndDestroy(unknownMedia);
+        }
+
+    // Append ids to the returned path
+    if (pPath)
+        {
+        ((CMPXCollectionPath*)pPath)->AppendL(ids.Array());
+        }
+    CleanupStack::PopAndDestroy(&ids);
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbCategory::CreateTableL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbCategory::CreateTableL(
+    RSqlDatabase& aDatabase,
+    TBool /* aCorruptTable */)
+    {
+    MPX_FUNC("CMPXDbCategory::CreateTableL");
+
+    // create the table
+    HBufC* query = PreProcessStringLC(KCategoryCreateTable);
+    User::LeaveIfError(aDatabase.Exec(*query));
+    CleanupStack::PopAndDestroy(query);
+
+    // do not create an index on the Name field
+    // as it only slows down the insert/update queries overall
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbCategory::DropTableL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbCategory::DropTableL(
+    RSqlDatabase& aDatabase)
+    {
+    MPX_FUNC("CMPXDbCategory::DropTableL");
+
+    HBufC* query = PreProcessStringLC(KCategoryDropTable);
+    User::LeaveIfError(aDatabase.Exec(*query));
+    CleanupStack::PopAndDestroy(query);
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbCategory::CheckTableL
+// ----------------------------------------------------------------------------
+//
+TBool CMPXDbCategory::CheckTableL(
+    RSqlDatabase& aDatabase)
+    {
+    MPX_FUNC("CMPXDbCategory::CheckTableL");
+
+    HBufC* query = PreProcessStringLC(KCategoryCheckTable);
+    TBool check(DoCheckTable(aDatabase, *query));
+    CleanupStack::PopAndDestroy(query);
+
+    return check;
+    }
+
+// End of File