upnpmediaserver/contentdirectoryservice/src/upnpmetadatastorage.cpp
changeset 0 7f85d04be362
child 30 5ec426854821
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/upnpmediaserver/contentdirectoryservice/src/upnpmetadatastorage.cpp	Thu Dec 17 08:52:00 2009 +0200
@@ -0,0 +1,2353 @@
+/** @file
+* Copyright (c) 2005-2006 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:  Metadata storage
+ *
+*/
+
+
+// INCLUDE FILES
+#include <upnpdominterface.h>
+#include "upnpmetadatastorage.h"
+#include "upnpcontentdirectoryglobals.h"
+#include "upnpobjectbean.h"
+#include "upnpelementbean.h"
+#include "upnpcdutils.h"
+#include "upnpresourcesbean.h"
+#include "upnpitem.h"
+#include "upnpelement.h"
+#include "upnpattributebean.h"
+#include "upnpcddbfactory.h"
+
+#define KLogFile _L("ContentDirectoryDb.log")
+#include "upnpcustomlog.h"
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::CUpnpMetadataStorage
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CUpnpMetadataStorage::CUpnpMetadataStorage()
+    {
+
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::ConstructL( const TDesC& aDatabaseFileName )
+    {
+    User::LeaveIfError( iFsSession.Connect( ) );
+    OpenDbL( aDatabaseFileName );
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CUpnpMetadataStorage* CUpnpMetadataStorage::NewLC(
+    const TDesC& aDatabaseFileName )
+    {
+    CUpnpMetadataStorage* self = new( ELeave ) CUpnpMetadataStorage();
+
+    CleanupStack::PushL( self );
+    self->ConstructL( aDatabaseFileName );
+
+    return self;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CUpnpMetadataStorage* CUpnpMetadataStorage::NewL(
+    const TDesC& aDatabaseFileName )
+    {
+    CUpnpMetadataStorage* self =
+            CUpnpMetadataStorage::NewLC( aDatabaseFileName );
+
+    CleanupStack::Pop( self );
+
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::~CUpnpMetadataStorage
+// Destructor
+// -----------------------------------------------------------------------------
+//    
+CUpnpMetadataStorage::~CUpnpMetadataStorage()
+    {
+    if ( iIsOpen )
+        {
+        iDatabase.Compact( );
+        }
+    iDatabase.Close( );
+    delete iFileStore;
+    iFsSession.Close( );
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::OpenDbL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::OpenDbL( const TFileName& aDatabaseFileName )
+    {
+    iFileStore = CPermanentFileStore::OpenL( iFsSession, aDatabaseFileName,
+        EFileRead|EFileWrite );
+    iFileStore->SetTypeL( iFileStore->Layout( ) );
+    iDatabase.OpenL( iFileStore, iFileStore->Root( ) );
+    CheckDatabaseL( );
+    iIsOpen = ETrue;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::DbChangedL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::DbChangedL( TInt aWeight )
+    {
+    iCompactCounter += aWeight;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::DbChangedL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::CompactDbL()
+    {
+    if ( iCompactCounter >= KCompactWeight )
+        {
+        iCompactCounter = 0;
+        User::LeaveIfError( iDatabase.Compact( ) );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::BeginTransactionL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::BeginTransactionL()
+    {
+    iDatabase.Begin( );
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::CommitTransactionL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::CommitTransactionL()
+    {
+    TInt err = iDatabase.Commit( );
+    if ( err != KErrNone )
+        {
+        iDatabase.Rollback( );
+        User::LeaveIfError( iDatabase.Recover( ) );
+        User::Leave( err );
+        }
+    CompactDbL( );
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::RollbackTransactionL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::RollbackTransactionL()
+    {
+    iDatabase.Rollback( );
+    User::LeaveIfError( iDatabase.Recover( ) );
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetObjectListL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpMetadataStorage::GetObjectListL( TInt aParentId,
+    RArray<TInt>& aList )
+    {
+    TUpnpErrorCode ret = CheckObjectRestrictionL( aParentId ); // make sure the parent exists
+    if ( ret != ENoSuchObject && ret != ENoContainer )
+        {
+        // prepare query
+        TBuf<sizeof(KGetObjectListSqlCmd)/KCharSize + KMaxIntegerLen> query;
+        query.Format( KGetObjectListSqlCmd, aParentId );
+        // prepare view
+        RDbView view;
+        User::LeaveIfError( view.Prepare( iDatabase, TDbQuery( query ),
+            view.EReadOnly ) );
+        CleanupClosePushL( view );
+        // evaluate
+        User::LeaveIfError( view.EvaluateAll( ) );
+        // for each object
+        const TInt KIdColNo=1;
+
+        while ( view.NextL( ) )
+            {
+            view.GetL( );
+            // get object
+            TInt childId = view.ColInt( KIdColNo );
+            aList.AppendL( childId );
+            }
+        //clean up
+        CleanupStack::PopAndDestroy( &view );
+        ret = EUpnpOk;
+        }
+    return ret;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetObjectListL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpMetadataStorage::GetItemListL( TInt aParentId,
+    RArray<TInt>& aList )
+    {
+    TUpnpErrorCode ret = CheckObjectRestrictionL( aParentId ); // make sure the parent exists
+    if ( ret != ENoSuchObject )
+        {
+        // prepare query
+        TBuf<sizeof(KGetItemListSqlCmd)/KCharSize + KMaxIntegerLen> query;
+        query.Format( KGetItemListSqlCmd, aParentId );
+        // prepare view
+        RDbView view;
+        User::LeaveIfError( view.Prepare( iDatabase, TDbQuery( query ),
+            view.EReadOnly ) );
+        CleanupClosePushL( view );
+        // evaluate
+        User::LeaveIfError( view.EvaluateAll( ) );
+        // for each object
+        const TInt KIdColNo=1;
+        while ( view.NextL( ) )
+            {
+            view.GetL( );
+            // get object
+            TInt childId = view.ColInt( KIdColNo );
+            aList.AppendL( childId );
+            }
+        //clean up
+        CleanupStack::PopAndDestroy( &view );
+        ret = EUpnpOk;
+        }
+    return ret;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetContainerListL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpMetadataStorage::GetContainerListL( TInt aParentId,
+    RArray<TInt>& aList )
+    {
+    TUpnpErrorCode ret = CheckObjectRestrictionL( aParentId ); // make sure the parent exists
+    if ( ret != ENoSuchObject )
+        {
+        // prepare query
+        TBuf<sizeof(KGetContainerListSqlCmd)/KCharSize + KMaxIntegerLen> query;
+        query.Format( KGetContainerListSqlCmd, aParentId );
+        // prepare view
+        RDbView view;
+        User::LeaveIfError( view.Prepare( iDatabase, TDbQuery( query ),
+            view.EReadOnly ) );
+        CleanupClosePushL( view );
+        // evaluate
+        User::LeaveIfError( view.EvaluateAll( ) );
+        // for each object
+        const TInt KIdColNo=1;
+        while ( view.NextL( ) )
+            {
+            view.GetL( );
+            // get object
+            TInt childId = view.ColInt( KIdColNo );
+            aList.AppendL( childId );
+            }
+        //clean up
+        CleanupStack::PopAndDestroy( &view );
+        ret = EUpnpOk;
+        }
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::CheckObjectRestrictionL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpMetadataStorage::CheckObjectRestrictionL( TInt aObjId )
+    {
+    TUpnpErrorCode ret = EUpnpUndefined;
+    RDbTable table;
+    CleanupClosePushL( table );
+    TDbSeekKey seekKey(aObjId);
+    User::LeaveIfError( table.Open( iDatabase, KObjectTableName,
+        table.EReadOnly ) );
+    User::LeaveIfError( table.SetIndex( KObjIdIndexName ) ); // use index
+    if ( table.SeekL( seekKey ) ) // find object
+        { // object found
+        table.GetL( );
+
+        CDbColSet* colSet = table.ColSetL( );
+        TDbColNo colNo(colSet->ColNo( KObjRestrictedColName ) );
+        if ( !table.ColUint8( colNo ) ) // is restricted?
+            { // OK
+            TDbColNo colNo(colSet->ColNo( KObjClassColName ) );
+            if ( table.ColDes8(colNo).Find( KContainerClass8 ) == 0 ) // check whether the object is a container
+                { // this is a container
+                ret = EUpnpOk;
+                }
+            else
+                { // there is such object but this is not a container
+                ret = ENoContainer;
+                }
+            }
+        else
+            {
+            ret = ERestrictedObject;
+            }
+        delete colSet;
+        }
+    else
+        { // no such object
+        ret = ENoSuchObject;
+        }
+
+    CleanupStack::PopAndDestroy( &table );
+    return ret;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::CheckObjectRestrictionL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpMetadataStorage::IsContainerL( TInt aObjId )
+    {
+    TBool ret = EFalse;
+    RDbTable table;
+    CleanupClosePushL( table );
+    TDbSeekKey seekKey(aObjId);
+    User::LeaveIfError( table.Open( iDatabase, KObjectTableName,
+        table.EReadOnly ) );
+    User::LeaveIfError( table.SetIndex( KObjIdIndexName ) ); // use index
+
+    if ( table.SeekL( seekKey ) ) // find object
+        { // object found
+        table.GetL( );
+
+        CDbColSet* colSet = table.ColSetL( );
+        TDbColNo colNo(colSet->ColNo( KObjClassColName ) );
+        if ( table.ColDes8(colNo).Find( KContainerClass8 ) == 0 ) // check whether the object is a container
+            { // this is a container
+            ret = ETrue;
+            }
+        delete colSet;
+        }
+    // clean up
+    CleanupStack::PopAndDestroy( &table );
+
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::AddMainTagAttrL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+TUpnpErrorCode CUpnpMetadataStorage::AddMainTagAttrL(
+    TXmlEngElement aElement, TInt aId, const TDesC8& aName )
+    {
+    TUpnpErrorCode ret = EUpnpUndefined;
+    // xml string of name
+
+    // is the attr exist?
+    TXmlEngAttr atr = aElement.AttributeNodeL( aName );
+    if ( atr.IsNull( ) )
+        { // attr does not exist - add
+        TBuf<sizeof(KSelectFromObjectSqlCmd)/KCharSize +
+        KMaxIntegerLen + KColNameMaxLenth> query;
+        query.Format( KSelectFromObjectSqlCmd, &aName, aId );
+
+        // Execute command
+        RDbView view;
+        CleanupClosePushL( view );
+        TInt dbErr = view.Prepare( iDatabase, TDbQuery( query ),
+            view.EReadOnly );
+        LOGSQL( "CUpnpContentDirectoryDb::AddMainTagAttrL",
+            "RDbView::Prepare", dbErr, &query );
+        if ( dbErr == KErrNone )
+            {
+            CleanupClosePushL( view );
+            User::LeaveIfError( view.EvaluateAll( ) );
+
+            // if there is a row, add attribute
+            if ( view.FirstL( ) )
+                {
+                // get row
+                view.GetL( );
+                // col's val as Des
+                HBufC8* buff = GetColDesValFromRowSetL( view, 1 );
+                CleanupStack::PushL( buff );
+                // prepare xml string of value
+                // add attributes
+                aElement.AddNewAttributeL( aName, *buff );
+                ret = EUpnpOk;
+                // clean up
+                CleanupStack::PopAndDestroy( buff );
+                }
+            else
+                { // no such object in the database
+                ret = ENoSuchObject;
+                }
+            }
+        else
+            { // probably the name of the attr was wrong - ignore
+            ret = ENoSuchObject;
+            }
+        // clean up
+        CleanupStack::PopAndDestroy( &view );
+        }
+    else // if(!atr.IsNull())
+        { // already exists - it is OK, do not need to do anything
+        ret = EUpnpOk;
+        }
+
+    return ret;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetElementViewL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+RDbView CUpnpMetadataStorage::GetElementViewL( TInt aObjId,
+    const TDesC8& aElName )
+    {
+    // convert to TDesC
+    HBufC* elName = HBufC::NewLC( aElName.Length( ) );
+    elName->Des().Copy( aElName );
+
+    // Prepare SQL command
+    HBufC* query = HBufC::NewLC( KSelectElmFromElmSqlCmd().Length( ) 
+                                + KNamedElFromElement().Length( ) 
+                                + KMaxIntegerLen 
+                                + elName->Length( ) );
+    TPtr queryPtr(query->Des( ));
+    queryPtr.Format( KSelectElmFromElmSqlCmd, aObjId );
+    queryPtr.AppendFormat( KNamedElFromElement, elName );
+    
+
+    // Execute command
+    RDbView view = GetEvaluatedViewL( queryPtr );
+    LOGSQL( "CUpnpContentDirectoryDb::GetElementViewL", "RDbView::Prepare",
+        0, &queryPtr );
+    CleanupStack::PopAndDestroy( query );
+    CleanupStack::PopAndDestroy( elName );
+
+    return view;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::AddAttributeL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+
+RDbView CUpnpMetadataStorage::GetObjViewL( TInt aObjId )
+    {
+    // Get data from object table
+    // Prepare SQL command
+    TBuf<sizeof(KSelectObjectFromObjSqlCmd)/KCharSize
+    + KMaxIntegerLen> query;
+    query.Format( KSelectObjectFromObjSqlCmd, aObjId );
+
+    LOGSQL( "CUpnpContentDirectoryDb::GetObjectL", "", 0, &query );
+
+    return GetEvaluatedViewL( query );
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::AddAttributeL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+RDbView CUpnpMetadataStorage::GetElementsViewL( TInt aObjectID, TBool aAll )
+    {
+    // Get data from element table
+    // Prepare SQL command
+    TBuf<sizeof(KSelectElmFromElmSqlCmd)/KCharSize
+    + sizeof(KOnlyRequiredFromElement)/KCharSize + KMaxIntegerLen> query;
+    query.Format( KSelectElmFromElmSqlCmd, aObjectID );
+
+    query.Format( KSelectElmFromElmSqlCmd, aObjectID );
+    if ( !aAll )
+        { // only required properties
+        query.Append( KOnlyRequiredFromElement );
+        }
+
+    LOGSQL( "CUpnpContentDirectoryDb::GetElementsViewL", "", 0, &query );
+
+    return GetEvaluatedViewL( query );
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::AddAttributeL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+RDbView CUpnpMetadataStorage::GetAttributesViewL( TInt aElementID, TBool aAll )
+    {
+    // Get data from element table
+    // Prepare SQL command
+    TBuf<sizeof(KSelectAtrFromAttrSqlCmd)/KCharSize
+    + sizeof(KOnlyRequiredFromAtr)/KCharSize + KMaxIntegerLen> query;
+    query.Format( KSelectAtrFromAttrSqlCmd, aElementID );
+    if ( !aAll )
+        { // only required attr are wanted
+        query.Append( KOnlyRequiredFromAtr );
+        }
+
+    LOGSQL( "CUpnpContentDirectoryDb::GetAttributesViewL", "", 0, &query );
+
+    return GetEvaluatedViewL( query );
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetAttributesViewByObjectIdL
+// -----------------------------------------------------------------------------
+//
+RDbView CUpnpMetadataStorage::GetAttributesViewByObjectIdL( TInt aObjectID,
+    TBool aAll )
+    {
+    // Get data from element table
+    // Prepare SQL command
+    TBuf<sizeof(KSelectAtrFromAttrByObjSqlCmd)/KCharSize
+    + sizeof(KOnlyRequiredFromAtr)/KCharSize + KMaxIntegerLen> query;
+    query.Format( KSelectAtrFromAttrByObjSqlCmd, aObjectID );
+    if ( !aAll )
+        { // only required attr are wanted
+        query.Append( KOnlyRequiredFromAtr );
+        }
+
+    LOGSQL( "CUpnpContentDirectoryDb::GetAttributesViewByObjectIdL", "", 0,
+        &query );
+
+    return GetEvaluatedViewL( query );
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::InsertElementL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpMetadataStorage::InsertElementL( const TXmlEngElement& aElement,
+    TInt aObjId )
+    {
+    // open table
+    RDbTable table;
+    User::LeaveIfError( table.Open( iDatabase, KElementTableName,
+        table.EUpdatable ) );
+    CleanupClosePushL( table );
+
+    // CdbColSet
+    CDbColSet* objColSet = table.ColSetL( );
+    CleanupStack::PushL( objColSet );
+
+    // rowset cursor to the beginning position
+    table.Reset( );
+
+    // insert empty row
+    table.InsertL( );
+
+    // elm_id
+    TInt elmId = GetNextKeyL( KElementTableName8 );
+    table.SetColL( objColSet->ColNo( KElmIdColName ), elmId );
+
+    // elm_name
+    HBufC8 * elmName = UpnpCdUtils::GetElmNameWithNsL( aElement );
+    CleanupStack::PushL( elmName );
+    table.SetColL( objColSet->ColNo( KElmNameColName ), *elmName );
+    CleanupStack::PopAndDestroy( elmName );
+
+    // elm_value
+    if ( aElement.Value().Length( ) )
+        {
+        TPtrC8 elmValue(aElement.Value( ) );
+        if ( elmValue.Length( ) > KMaxUpnpLongStringLen )
+            { // too long
+            User::Leave( EActionFailed );
+            }
+        // use write stream
+        RDbColWriteStream ws;
+        ws.OpenLC( table, objColSet->ColNo( KElmValueColName ) );
+        ws.WriteL( elmValue ); // write value
+        ws.CommitL( );
+        CleanupStack::PopAndDestroy( &ws );
+        }
+
+    // elm_has_attribute
+    table.SetColL( objColSet->ColNo( KElmHasAttrColName ),
+        aElement.HasAttributes( ) );
+
+    // elm_obj_id
+    table.SetColL( objColSet->ColNo( KElmObjIdColName ), aObjId );
+
+    // elm_is_required
+    table.SetColL( objColSet->ColNo( KElmIsRequiredColName ),
+        UpnpCdUtils::IsElementRequiredL( aElement ) );
+
+    // complete insertion
+    table.PutL( );
+
+    DbChangedL( KExecuteWeight );
+
+    // clean up
+    CleanupStack::PopAndDestroy( objColSet );
+    CleanupStack::PopAndDestroy( &table );
+
+    return elmId;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::CreatePathValL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+HBufC8* CUpnpMetadataStorage::CreatePathValL( const TXmlEngElement& aElement )
+    {
+    TPtrC8
+            parentIdPtr(UpnpDomInterface::GetAttrValueL( aElement, KParentID ));
+    TLex8 lexer(parentIdPtr);
+    TInt parentId;
+    User::LeaveIfError( lexer.Val( parentId ) );
+
+    return CreatePathValL( parentId );
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::CreatePathValL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+HBufC8* CUpnpMetadataStorage::CreatePathValL( TInt aParentId )
+    {
+    HBufC8* path = NULL;
+    User::LeaveIfNull( path = GetObjectPathL( aParentId ) );
+
+    CleanupStack::PushL( path );
+
+    HBufC8* tmp = HBufC8::NewL( path->Length( ) 
+                                + KPathSeparator().Length( ) 
+                                + KMaxIntegerLen );
+    TPtr8 tmpPtr(tmp->Des( ));
+    tmpPtr.Copy( *path );
+    tmpPtr.Append( KPathSeparator );
+
+    TBuf<KMaxIntegerLen> num;
+    num.Num( aParentId );
+    tmpPtr.Append( num );
+
+    CleanupStack::PopAndDestroy( path );
+
+    return tmp;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::InsertAttributeL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::InsertAttributeL( const TXmlEngAttr aAttr,
+    TInt aElmId, TBool aIsRequired, TInt aObjId )
+    {
+
+    // open table
+    RDbTable table;
+    User::LeaveIfError( table.Open( iDatabase, KAttributeTableName,
+        table.EUpdatable ) );
+    CleanupClosePushL( table );
+
+    // CdbColSet
+    CDbColSet* objColSet = table.ColSetL( );
+    CleanupStack::PushL( objColSet );
+
+    // rowset cursor to the beginning position
+    table.Reset( );
+
+    // insert empty row
+    table.InsertL( );
+
+    // atr_id
+    table.SetColL( objColSet->ColNo( KAtrIdColName ),
+        GetNextKeyL( KAttributeTableName8 ) ); // leaves if error
+
+    // atr_name
+    table.SetColL( objColSet->ColNo( KAtrNameColName ), aAttr.Name( ) ); // name cannot be null
+
+    // atr_value
+    if ( aAttr.Value().Length( ) )
+        {
+        TPtrC8 atrValue(aAttr.Value( ) );
+        if ( atrValue.Length( ) > KMaxUpnpLongStringLen )
+            { // too long
+            User::Leave( EActionFailed );
+            }
+        // use write stream
+        RDbColWriteStream ws;
+        ws.OpenLC( table, objColSet->ColNo( KAtrValueColName ) );
+        ws.WriteL( atrValue ); // write value
+        ws.CommitL( );
+        CleanupStack::PopAndDestroy( &ws );
+        }
+
+    // atr_elm_id
+    table.SetColL( objColSet->ColNo( KAtrElmIdColName ), aElmId );
+
+    // atr_is_required
+    table.SetColL( objColSet->ColNo( KAtrIsRequiredColName ), aIsRequired );
+
+    // atr_obj_id
+    table.SetColL( objColSet->ColNo( KAtrIdObjColName ), aObjId );
+
+    // complete insertion
+    table.PutL( );
+
+    DbChangedL( KExecuteWeight );
+
+    // clean up
+    CleanupStack::PopAndDestroy( objColSet );
+    CleanupStack::PopAndDestroy( &table );
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::InsertObjectIntoObjectTableL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::InsertObjectIntoObjectTableL(
+    const TXmlEngElement& aElement )
+    {
+    // open table
+    RDbTable table;
+    User::LeaveIfError( table.Open( iDatabase, KObjectTableName,
+        table.EUpdatable ) );
+    CleanupClosePushL( table );
+
+    // CdbColSet
+    CDbColSet* objColSet = table.ColSetL( );
+    CleanupStack::PushL( objColSet );
+
+    // rowset cursor to the beginning position
+    table.Reset( );
+
+    // insert empty row
+    table.InsertL( );
+
+    // set attributes
+    RXmlEngNodeList<TXmlEngAttr> attrList;
+    CleanupClosePushL( attrList );
+    aElement.GetAttributes( attrList );
+    while ( attrList.HasNext( ) )
+        {
+        // get next
+        TXmlEngAttr attr = attrList.Next( );
+
+        // col ordinal
+        HBufC* colName = HBufC::NewLC( attr.Name().Length( ) );
+        colName->Des().Copy( attr.Name( ) );
+        TDbColNo colNo = objColSet->ColNo( *colName );
+        CleanupStack::PopAndDestroy( colName );
+
+        // insert if exists
+        if ( colNo != KDbNullColNo )
+            { // (not any string attribute in the main element)
+            HBufC8* tmp = attr.Value().AllocLC( );
+            UpnpCdUtils::ReplaceTrueFalse( tmp );// true -> 1, false -> 0
+            TLex8 lexer(*tmp);
+            TInt num;
+            User::LeaveIfError( lexer.Val( num ) ); // string -> integer
+            // set value
+            table.SetColL( colNo, num );
+            CleanupStack::PopAndDestroy( tmp );
+            }
+        }
+    CleanupStack::Check( &attrList );
+
+    // set title
+    TXmlEngElement objTitle;
+    UpnpDomInterface::GetElementL( aElement, objTitle, KObjTiltleColName8( ) );
+    table.SetColL( objColSet->ColNo( KObjTiltleColName ), objTitle.Value( ) );
+    CleanupStack::Check( &attrList );
+
+    // set class
+    TXmlEngElement objClass;
+    UpnpDomInterface::GetElementL( aElement, objClass, KObjClassColName8( ) );
+    table.SetColL( objColSet->ColNo( KObjClassColName ), objClass.Value( ) );
+    CleanupStack::Check( &attrList );
+
+    // set path
+    HBufC8* path = CreatePathValL( aElement );
+    CleanupStack::PushL( path );
+    table.SetColL( objColSet->ColNo( KObjPathColName ), *path );
+    CleanupStack::PopAndDestroy( path );
+    CleanupStack::Check( &attrList );
+
+    // complete insertion
+    table.PutL( );
+
+    DbChangedL( KExecuteWeight );
+
+    // clean up
+    CleanupStack::PopAndDestroy( &attrList );
+    CleanupStack::PopAndDestroy( objColSet );
+    CleanupStack::PopAndDestroy( &table );
+
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetNextKeyForTableL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpMetadataStorage::GetNextKeyL( const TDesC8& aName )
+    {
+    TInt ret = KErrNotFound;
+    RDbTable table;
+    CleanupClosePushL( table );
+    TDbSeekKey seekKey(aName);
+    User::LeaveIfError( table.Open( iDatabase, KSequencesTableName,
+        table.EUpdatable ) );
+    User::LeaveIfError( table.SetIndex( KSeqColNameIndexName ) ); // use index
+    if ( table.SeekL( seekKey ) ) // find object
+        { // object found
+        table.GetL( );
+        CDbColSet* colSet = table.ColSetL( );
+        CleanupStack::PushL( colSet );
+        TDbColNo colNo(colSet->ColNo( KSeqNextKeyColName ) );
+        ret = table.ColInt( colNo );
+        table.UpdateL( );
+        table.SetColL( colNo, ret + 1 );
+        table.PutL( );
+
+        DbChangedL( KExecuteWeight );
+
+        CleanupStack::PopAndDestroy( colSet );
+        }
+    else
+        { // no such object
+        User::Leave( KErrCorrupt );
+        }
+    // clean up
+    CleanupStack::PopAndDestroy( &table );
+
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetNextKeyForTableL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpMetadataStorage::GetNextKeyL( const TDesC8& aName, TInt aAmount )
+    {
+    TInt ret = KErrNotFound;
+    RDbTable table;
+    CleanupClosePushL( table );
+    TDbSeekKey seekKey(aName);
+    User::LeaveIfError( table.Open( iDatabase, KSequencesTableName,
+        table.EUpdatable ) );
+    User::LeaveIfError( table.SetIndex( KSeqColNameIndexName ) ); // use index
+    if ( table.SeekL( seekKey ) ) // find object
+        { // object found
+        table.GetL( );
+        CDbColSet* colSet = table.ColSetL( );
+        CleanupStack::PushL( colSet );
+        TDbColNo colNo(colSet->ColNo( KSeqNextKeyColName ) );
+        ret = table.ColInt( colNo );
+        table.UpdateL( );
+        table.SetColL( colNo, ret + aAmount );
+        table.PutL( );
+
+        DbChangedL( KExecuteWeight );
+
+        CleanupStack::PopAndDestroy( colSet );
+        }
+    else
+        { // no such object
+        User::Leave( KErrCorrupt );
+        }
+    // clean up
+    CleanupStack::PopAndDestroy( &table );
+
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::NextKeyL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpMetadataStorage::NextKeyL( const TDesC8& aName )
+    {
+    TInt ret = KErrNotFound;
+    RDbTable table;
+    CleanupClosePushL( table );
+    TDbSeekKey seekKey(aName);
+    User::LeaveIfError( table.Open( iDatabase, KSequencesTableName,
+        table.EReadOnly ) );
+    User::LeaveIfError( table.SetIndex( KSeqColNameIndexName ) ); // use index
+    if ( table.SeekL( seekKey ) ) // find object
+        { // object found
+        table.GetL( );
+        CDbColSet* colSet = table.ColSetL( );
+        CleanupStack::PushL( colSet );
+        TDbColNo colNo(colSet->ColNo( KSeqNextKeyColName ) );
+        ret = table.ColInt( colNo );
+
+        CleanupStack::PopAndDestroy( colSet );
+        }
+    else
+        { // no such object
+        User::Leave( KErrCorrupt );
+        }
+    // clean up
+    CleanupStack::PopAndDestroy( &table );
+
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::ReferedObjectIdL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpMetadataStorage::ReferedObjectIdL( TInt aObjectId )
+    {
+    TInt ret = KErrNotFound;
+    TBuf<sizeof(KSelectFromObjectSqlCmd)/KCharSize
+    + KMaxIntegerLen + KColNameMaxLenth> query;
+    query.Format( KSelectFromObjectSqlCmd, &KObjRefIdColName, aObjectId );
+
+    // Execute command
+    RDbView view;
+    CleanupClosePushL( view );
+    TInt dbErr = view.Prepare( iDatabase, TDbQuery( query ), view.EReadOnly );
+    LOGSQL( "CUpnpContentDirectoryDb::ReferedObjectIdL", "RDbView::Prepare",
+        dbErr, &query );
+    if ( dbErr == KErrNone )
+        {
+        User::LeaveIfError( view.Evaluate( ) );
+        if ( view.FirstL( ) )
+            {
+            // get col number -  there can by only one column but just in case get by name
+            CDbColSet* colSet = view.ColSetL( );
+            const TInt colNo = colSet->ColNo( KObjRefIdColName );
+            delete colSet;
+
+            view.GetL( );
+            if ( !view.IsColNull( colNo ) )
+                {
+                ret = view.ColInt( colNo );
+                }
+            }
+        }
+    // clean up
+    CleanupStack::PopAndDestroy( &view );
+
+    return ret;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetElmIdForAttrL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpMetadataStorage::GetElmIdForAttrL( const TDesC8& aAttrName,
+    const TDesC8& aAttrVal )
+    {
+    // convert to unicode
+    HBufC* attrName = UpnpCdUtils::Des8ToDesLC( aAttrName );
+    HBufC* attrVal = UpnpCdUtils::Des8ToDesLC( aAttrVal );
+
+    TInt elmId = KErrNotFound;
+    HBufC* query = HBufC::NewLC( aAttrVal.Length( ) 
+                                 + KSelectFromSqlCmd().Length( ) 
+                                 + KAtrElmIdColName().Length( ) 
+                                 + KAttributeTableName().Length( ) 
+                                 + KAtrValueColName().Length( ) 
+                                 + KAndConditionSqlCmd().Length( ) 
+                                 + KAtrNameColName().Length( ) 
+                                 + aAttrName.Length( ) );
+    TPtr queryPtr(query->Des( ));
+    // prepare format string
+    HBufC* fmt = HBufC::NewLC( KSelectFromSqlCmd().Length( ) + KAndConditionSqlCmd().Length( ) );
+    TPtr fmtPtr(fmt->Des( ));
+    fmtPtr.Copy( KSelectFromSqlCmd );
+    fmtPtr.Append( KAndConditionSqlCmd );
+    // format query
+    queryPtr.Format( fmtPtr, &KAtrElmIdColName, &KAttributeTableName,
+        &KAtrNameColName, attrName, &KAtrValueColName, attrVal );
+    // clean up format string
+    CleanupStack::PopAndDestroy( fmt );
+
+    RDbView view;
+    CleanupClosePushL( view );
+    TInt dbErr = view.Prepare( iDatabase, TDbQuery( queryPtr ),
+        view.EReadOnly );
+    if ( dbErr == KErrNone )
+        {
+        User::LeaveIfError( view.Evaluate( ) );
+        if ( view.FirstL( ) )
+            {
+            // get col number -  there can by only one column but just in case get by name
+            CDbColSet* colSet = view.ColSetL( );
+            const TInt colNo = colSet->ColNo( KAtrElmIdColName );
+            delete colSet;
+
+            view.GetL( );
+            if ( !view.IsColNull( colNo ) )
+                {
+                elmId = view.ColInt( colNo );
+                }
+            }
+        }
+    // clean up
+    CleanupStack::PopAndDestroy( &view );
+    CleanupStack::PopAndDestroy( query );
+    CleanupStack::PopAndDestroy( attrVal );
+    CleanupStack::PopAndDestroy( attrName );
+    return elmId;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetObjIdForElmIdL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpMetadataStorage::GetObjIdForElmIdL( TInt aId )
+    {
+    TInt objId = KErrNotFound;
+    HBufC* query = HBufC::NewLC( KMaxIntegerLen + KSelectFromNumSqlCmd().Length( ) 
+                                + KElementTableName().Length( ) 
+                                + KElmObjIdColName().Length( ) 
+                                + KElmIdColName().Length( ) );
+    TPtr queryPtr(query->Des( ));
+    queryPtr.Format( KSelectFromNumSqlCmd, &KElmObjIdColName,
+        &KElementTableName, &KElmIdColName, aId );
+
+    RDbView view;
+    CleanupClosePushL( view );
+    TInt dbErr = view.Prepare( iDatabase, TDbQuery( queryPtr ),
+        view.EReadOnly );
+    if ( dbErr == KErrNone )
+        {
+        User::LeaveIfError( view.Evaluate( ) );
+        if ( view.FirstL( ) )
+            {
+            // get col number -  there can by only one column but just in case get by name
+            CDbColSet* colSet = view.ColSetL( );
+            const TInt colNo = colSet->ColNo( KElmObjIdColName );
+            delete colSet;
+
+            view.GetL( );
+            if ( !view.IsColNull( colNo ) )
+                {
+                objId = view.ColInt( colNo );
+                }
+            }
+        }
+    // clean up
+    CleanupStack::PopAndDestroy( &view );
+    CleanupStack::PopAndDestroy( query );
+    return objId;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetObjIdByAttrLikeL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpMetadataStorage::GetElmIdForAttrLikeL( const TDesC8& aAttrName,
+    const TDesC8& aAttrVal )
+    {
+    //convert to unicode 
+    HBufC* attrVal = UpnpCdUtils::Des8ToDesLC( aAttrVal );
+    HBufC* attrName = UpnpCdUtils::Des8ToDesLC( aAttrName );
+
+    // query buf
+    TInt elmId = KErrNotFound;
+    HBufC* query = HBufC::NewLC( attrVal->Length( ) 
+                                + KSelectFromSqlCmd().Length( ) 
+                                + KAtrElmIdColName().Length( ) 
+                                + KAttributeTableName().Length( ) 
+                                + KAtrValueColName().Length( ) 
+                                + KAndLikeConditionSqlCmd().Length( ) 
+                                + KAtrNameColName().Length( ) 
+                                + attrName->Length( ) );
+    TPtr queryPtr(query->Des( ));
+    // prepare format string
+    HBufC* fmt = HBufC::NewLC( KSelectFromSqlCmd().Length( ) + KAndLikeConditionSqlCmd().Length( ) );
+    TPtr fmtPtr(fmt->Des( ));
+    fmtPtr.Copy( KSelectFromSqlCmd );
+    fmtPtr.Append( KAndLikeConditionSqlCmd );
+    // format query
+    queryPtr.Format( fmtPtr, &KAtrElmIdColName, &KAttributeTableName,
+        &KAtrNameColName, attrName, &KAtrValueColName, attrVal );
+    // clean up format string
+    CleanupStack::PopAndDestroy( fmt );
+
+    RDbView view;
+    CleanupClosePushL( view );
+    TInt dbErr = view.Prepare( iDatabase, TDbQuery( queryPtr ),
+        view.EReadOnly );
+    if ( dbErr == KErrNone )
+        {
+        User::LeaveIfError( view.Evaluate( ) );
+        if ( view.FirstL( ) )
+            {
+            // get col number -  there can by only one column but just in case get by name
+            CDbColSet* colSet = view.ColSetL( );
+            const TInt colNo = colSet->ColNo( KAtrElmIdColName );
+            delete colSet;
+
+            view.GetL( );
+            if ( !view.IsColNull( colNo ) )
+                {
+                elmId = view.ColInt( colNo );
+                }
+            }
+        }
+    // clean up
+    CleanupStack::PopAndDestroy( &view );
+    CleanupStack::PopAndDestroy( query );
+    CleanupStack::PopAndDestroy( attrName );
+    CleanupStack::PopAndDestroy( attrVal );
+    return elmId;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetParentIdL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpMetadataStorage::GetParentIdL( TInt aObjId )
+    {
+    TInt objId=KErrGeneral;
+    HBufC* query = HBufC::NewLC( KSelectFromNumSqlCmd().Length( ) 
+                                + KObjParentIdColName().Length( ) 
+                                + KObjectTableName().Length( ) 
+                                + KObjIdColName().Length( ) 
+                                + KMaxIntegerLen );
+    TPtr queryPtr(query->Des( ));
+    queryPtr.Format( KSelectFromNumSqlCmd, &KObjParentIdColName,
+        &KObjectTableName, &KObjIdColName, aObjId );
+
+    RDbView view;
+    CleanupClosePushL( view );
+    TInt dbErr = view.Prepare( iDatabase, TDbQuery( queryPtr ),
+        view.EReadOnly );
+    if ( dbErr == KErrNone )
+        {
+        User::LeaveIfError( view.Evaluate( ) );
+        if ( view.FirstL( ) )
+            {
+            CDbColSet* colSet = view.ColSetL( );
+            const TInt colNo = colSet->ColNo( KObjParentIdColName );
+            delete colSet;
+
+            view.GetL( );
+            if ( !view.IsColNull( colNo ) )
+                {
+                objId = view.ColInt( colNo );
+                }
+            }
+        }
+    // clean up
+    CleanupStack::PopAndDestroy( &view );
+    CleanupStack::PopAndDestroy( query );
+    return objId;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetChildCountL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpMetadataStorage::GetChildCountL( TInt aObjId )
+    {
+    TInt childCount = KErrGeneral;
+
+    HBufC* query = HBufC::NewLC( KSelectFromNumSqlCmd().Length( ) 
+                                 + KObjIdColName().Length( ) 
+                                 + KObjectTableName().Length( ) 
+                                 + KObjParentIdColName().Length( ) 
+                                 + KMaxIntegerLen );
+    TPtr queryPtr(query->Des( ));
+    queryPtr.Format( KSelectFromNumSqlCmd, &KObjIdColName, &KObjectTableName,
+        &KObjParentIdColName, aObjId );
+
+    RDbView view;
+    CleanupClosePushL( view );
+    TInt dbErr = view.Prepare( iDatabase, TDbQuery( queryPtr ),
+        view.EReadOnly );
+    if ( dbErr == KErrNone )
+        {
+        User::LeaveIfError( view.EvaluateAll( ) );
+        childCount = view.CountL( );
+        }
+    // clean up
+    CleanupStack::PopAndDestroy( &view );
+    CleanupStack::PopAndDestroy( query );
+    return childCount;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::DeleteResElL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::DeleteResElL( const TDesC& aResVal, TInt ObjId )
+    {
+    HBufC* query = HBufC::NewLC( KDeleteResElSqlCmd().Length( ) + aResVal.Length( ) + KMaxIntegerLen );
+    TPtr SqlCmd(query->Des( ));
+    SqlCmd.Format( KDeleteResElSqlCmd, &aResVal, ObjId );
+
+    // execute
+    ExecuteL( SqlCmd );
+
+    // clean up
+    CleanupStack::PopAndDestroy( query );
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::DeleteResElL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::ExecuteL( const TDesC& aSqlCmd )
+    {
+    // execute
+    TInt err = iDatabase.Execute( aSqlCmd );
+    LOGSQL( "CUpnpContentDirectoryDb::DeleteResElL", "iDataBase.Execute",
+        err, &aSqlCmd );
+    User::LeaveIfError( err );
+
+    // db compact
+    DbChangedL( KExecuteWeight );
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::DeleteResElL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+RDbView CUpnpMetadataStorage::GetViewOfObjectListForResL( const TDesC& aResVal )
+    {
+    HBufC* query = HBufC::NewLC( KSelectFromSqlCmd().Length( ) 
+                                + KElmObjIdColName().Length( ) 
+                                + KElementTableName().Length( ) 
+                                + KElmValueColName().Length( ) 
+                                + aResVal.Length( )
+                                + KNamedElFromElement().Length()
+                                + KRes16().Length());
+    TPtr queryPtr(query->Des( ));
+    queryPtr.Format( KSelectFromSqlCmd, &KElmObjIdColName,
+        &KElementTableName, &KElmValueColName, &aResVal );
+    queryPtr.AppendFormat( KNamedElFromElement, &KRes16 );
+
+    RDbView view = GetEvaluatedViewL( queryPtr );
+
+    CleanupStack::PopAndDestroy( query );
+
+    return view;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetViewOfElmIdByNameAndValLC
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+RDbView CUpnpMetadataStorage::GetViewOfElmIdByNameAndValL(
+    const TDesC& aElmName, const TDesC& aElmValue )
+    {
+    HBufC* resValReplaced16 = UpnpCdUtils::EscapeAposL( aElmValue );
+    HBufC* query = HBufC::NewLC( KSelectFromSqlCmd().Length( ) 
+                                + KElmIdColName().Length( ) 
+                                + KElementTableName().Length( ) 
+                                + KElmNameColName().Length( ) 
+                                + aElmName.Length( ) 
+                                + KAndConditionSqlCmd().Length( ) 
+                                + KElmValueColName().Length( ) 
+                                + resValReplaced16->Des().Length( ) );
+    TPtr queryPtr(query->Des( ));
+
+    // format query
+    queryPtr.Format( KSelectFromSqlCmd, &KElmIdColName, &KElementTableName,
+        &KElmNameColName, &aElmName );
+    queryPtr.AppendFormat( KAndConditionSqlCmd, &KElmValueColName,
+        resValReplaced16 );
+
+    RDbView view = GetEvaluatedViewL( queryPtr );
+
+    CleanupStack::PopAndDestroy( query );
+
+    delete resValReplaced16;
+    return view;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetAttrViewL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+RDbView CUpnpMetadataStorage::GetAttrViewL( const TDesC8& aAttrName,
+    const TDesC8& aAttrVal )
+    {
+    HBufC* attrNameBuf = UpnpCdUtils::Des8ToDesLC( aAttrName );
+    HBufC* attrValueBuf = UpnpCdUtils::Des8ToDesLC( aAttrVal );
+
+    HBufC* query = HBufC::NewLC( KSelectAttributeByValueSqlCmd().Length( ) + aAttrName.Length( ) + aAttrVal.Length( )
+
+    );
+    TPtr queryPtr(query->Des( ));
+
+    // format query
+    queryPtr.Format( KSelectAttributeByValueSqlCmd( ), attrValueBuf,
+        attrNameBuf );
+
+    RDbView view = GetEvaluatedViewL( queryPtr );
+
+    CleanupStack::PopAndDestroy( query );
+    CleanupStack::PopAndDestroy( attrValueBuf );
+    CleanupStack::PopAndDestroy( attrNameBuf );
+
+    return view;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetAttrViewL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+RDbView CUpnpMetadataStorage::GetAttrViewL( TInt aElmId,
+    const TDesC8& aAttrName )
+    {
+    // convert ot unicode
+    HBufC* attrNameBuf = UpnpCdUtils::Des8ToDesLC( aAttrName );
+
+    HBufC* query = HBufC::NewLC( KSelectFromNumSqlCmd().Length( ) 
+                                 + KAtrValueColName().Length( ) 
+                                 + KAttributeTableName().Length( ) 
+                                 + KAtrElmIdColName().Length( ) 
+                                 + KMaxIntegerLen 
+                                 + KAndConditionSqlCmd().Length( ) 
+                                 + KAtrNameColName().Length( ) 
+                                 + aAttrName.Length( ) );
+    TPtr queryPtr(query->Des( ));
+    // prepare format string
+    HBufC* fmt = HBufC::NewLC( KSelectFromNumSqlCmd().Length( ) + KAndConditionSqlCmd().Length( ) );
+    TPtr fmtPtr(fmt->Des( ));
+    fmtPtr.Copy( KSelectFromNumSqlCmd );
+    fmtPtr.Append( KAndConditionSqlCmd );
+    // format query
+    queryPtr.Format( fmtPtr, &KAsterisk, &KAttributeTableName,
+        &KAtrElmIdColName, aElmId, &KAtrNameColName, attrNameBuf );
+
+    CleanupStack::PopAndDestroy( fmt );
+
+    RDbView view = GetEvaluatedViewL( queryPtr );
+
+    CleanupStack::PopAndDestroy( query );
+    CleanupStack::PopAndDestroy( attrNameBuf );
+
+    return view;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetAttrViewByObjectIdL
+// -----------------------------------------------------------------------------
+//
+RDbView CUpnpMetadataStorage::GetAttrViewByObjectIdL( TInt aObjectId,
+    const TDesC8& aAttrName )
+    {
+    // convert ot unicode
+    HBufC* attrNameBuf = UpnpCdUtils::Des8ToDesLC( aAttrName );
+
+    HBufC* query = HBufC::NewLC( KSelectFromNumSqlCmd().Length( ) 
+                                 + KAtrValueColName().Length( ) 
+                                 + KAttributeTableName().Length( ) 
+                                 + KAtrIdObjColName().Length( ) 
+                                 + KMaxIntegerLen 
+                                 + KAndConditionSqlCmd().Length( ) 
+                                 + KAtrNameColName().Length( ) 
+                                 + aAttrName.Length( ) );
+    TPtr queryPtr(query->Des( ));
+    // prepare format string
+    HBufC* fmt = HBufC::NewLC( KSelectFromNumSqlCmd().Length( ) + KAndConditionSqlCmd().Length( ) );
+    TPtr fmtPtr(fmt->Des( ));
+    fmtPtr.Copy( KSelectFromNumSqlCmd );
+    fmtPtr.Append( KAndConditionSqlCmd );
+    // format query
+    queryPtr.Format( fmtPtr, &KAsterisk, &KAttributeTableName,
+        &KAtrIdObjColName, aObjectId, &KAtrNameColName, attrNameBuf );
+
+    CleanupStack::PopAndDestroy( fmt );
+
+    RDbView view = GetEvaluatedViewL( queryPtr );
+
+    CleanupStack::PopAndDestroy( query );
+    CleanupStack::PopAndDestroy( attrNameBuf );
+
+    return view;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectoryDb::PrepareViewL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+RDbView CUpnpMetadataStorage::PrepareViewL( const TDesC& aSqlQuery )
+    {
+    RDbView view;
+    TInt dbErr = view.Prepare( iDatabase, TDbQuery( aSqlQuery ),
+        view.EReadOnly );
+    LOGSQL( "CUpnpMetadataStorage::GetViewL", "RDbView::Prepare", dbErr,
+        &aSqlQuery );
+    User::LeaveIfError( dbErr );
+
+    return view;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectoryDb::GetEvaluatedViewL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+RDbView CUpnpMetadataStorage::GetEvaluatedViewL( const TDesC& aSqlQuery )
+    {
+    RDbView view = PrepareViewL( aSqlQuery );
+
+    // evaluate
+    TInt dbErr = view.EvaluateAll( );
+    LOGCD( "CUpnpMetadataStorage::GetViewLC", "RDbView::EvaluateAll", dbErr,
+        "" );
+    User::LeaveIfError( dbErr );
+
+    return view;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetObjectPathL 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+HBufC8* CUpnpMetadataStorage::GetObjectPathL( TInt aObjId )
+    {
+    HBufC8* ret = NULL;
+    HBufC* query = HBufC::NewLC( KSelectFromNumSqlCmd().Length( ) 
+                                + KObjPathColName().Length( ) 
+                                + KObjectTableName().Length( ) 
+                                + KObjIdColName().Length( ) 
+                                + KMaxIntegerLen );
+    TPtr queryPtr(query->Des( ));
+    // format query
+    queryPtr.Format( KSelectFromNumSqlCmd, &KObjPathColName,
+        &KObjectTableName, &KObjIdColName, aObjId );
+
+    RDbView view;
+    CleanupClosePushL( view );
+    TInt dbErr = view.Prepare( iDatabase, TDbQuery( queryPtr ),
+        view.EReadOnly );
+    if ( dbErr == KErrNone )
+        {
+        User::LeaveIfError( view.EvaluateAll( ) );
+
+        CDbColSet* colSet = view.ColSetL( );
+        const TInt colNo = colSet->ColNo( KObjPathColName );
+        delete colSet;
+
+        if ( view.FirstL( ) )
+            {
+            view.GetL( );
+            if ( !view.IsColNull( colNo ) )
+                {
+                ret = view.ColDes8( colNo ).AllocL( );
+                }
+            }
+        }
+    // clean up
+    CleanupStack::PopAndDestroy( &view );
+    CleanupStack::PopAndDestroy( query );
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetObjectTitleL 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+HBufC8* CUpnpMetadataStorage::GetObjectTitleL( TInt aObjId )
+    {
+    HBufC8* ret = NULL;
+    HBufC* query = HBufC::NewLC( KSelectFromNumSqlCmd().Length( ) 
+                                + KObjTiltleColName().Length( ) 
+                                + KObjectTableName().Length( ) 
+                                + KObjIdColName().Length( ) 
+                                + KMaxIntegerLen );
+    TPtr queryPtr(query->Des( ));
+    // format query
+    queryPtr.Format( KSelectFromNumSqlCmd, &KObjTiltleColName,
+        &KObjectTableName, &KObjIdColName, aObjId );
+
+    RDbView view;
+    CleanupClosePushL( view );
+    TInt dbErr = view.Prepare( iDatabase, TDbQuery( queryPtr ),
+        view.EReadOnly );
+    if ( dbErr == KErrNone )
+        {
+        User::LeaveIfError( view.EvaluateAll( ) );
+
+        CDbColSet* colSet = view.ColSetL( );
+        const TInt colNo = colSet->ColNo( KObjTiltleColName );
+        delete colSet;
+
+        if ( view.FirstL( ) )
+            {
+            view.GetL( );
+            if ( !view.IsColNull( colNo ) )
+                {
+                ret = view.ColDes8( colNo ).AllocL( );
+                }
+            }
+        }
+    // clean up
+    CleanupStack::PopAndDestroy( &view );
+    CleanupStack::PopAndDestroy( query );
+    return ret;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetResourceL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CUpnpResourcesBean* CUpnpMetadataStorage::GetResourceL( TInt64 aResId )
+    {
+    CUpnpResourcesBean* resBn = NULL;
+    RDbTable table;
+    CleanupClosePushL( table );
+    TDbSeekKey seekKey(aResId);
+    User::LeaveIfError( table.Open( iDatabase, KResourcesTableName,
+        table.EUpdatable ) );
+    User::LeaveIfError( table.SetIndex( KRscIdIndexName ) ); // use index
+    if ( table.SeekL( seekKey ) ) // find object
+        { // object found
+        table.GetL( );
+        // table bean
+        resBn = CUpnpResourcesBean::NewL( table );
+        }
+    // clean up
+    CleanupStack::PopAndDestroy( &table );
+    return resBn;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::DeleteResourceL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::DeleteResourceByObjIdL( TInt aObjId,
+    TBool aDeleteFile )
+    {
+    RDbTable table;
+    CleanupClosePushL( table );
+    TDbSeekKey seekKey(aObjId);
+    User::LeaveIfError( table.Open( iDatabase, KResourcesTableName,
+        table.EUpdatable ) );
+    User::LeaveIfError( table.SetIndex( KRscIdObjIndexName ) ); // use index
+    while ( table.SeekL( seekKey ) ) // find object
+        { // object found
+        table.GetL( );
+
+        // table bean
+        CUpnpResourcesBean* resBn = CUpnpResourcesBean::NewLC( table );
+
+        if ( aDeleteFile && !resBn->IsReadonly( ) && resBn->IsThumbnail( ) )
+            { // delete the file
+            DeleteFileL( resBn->Path( ) );
+            }
+
+        // clean up 
+        CleanupStack::PopAndDestroy( resBn );
+
+        // delete the row
+        table.DeleteL( );
+        }
+    // clean up
+    CleanupStack::PopAndDestroy( &table );
+
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::DeleteResourceByResIdL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::DeleteResourceByResIdL( TInt64 aResId,
+    TBool aDeleteFile )
+    {
+    RDbTable table;
+    CleanupClosePushL( table );
+    TDbSeekKey seekKey(aResId);
+    User::LeaveIfError( table.Open( iDatabase, KResourcesTableName,
+        table.EUpdatable ) );
+    User::LeaveIfError( table.SetIndex( KRscIdIndexName ) ); // use index
+    while ( table.SeekL( seekKey ) ) // find object
+        { // object found
+        table.GetL( );
+
+        // table bean
+        CUpnpResourcesBean* resBn = CUpnpResourcesBean::NewLC( table );
+
+        if ( aDeleteFile && !resBn->IsReadonly( ) && resBn->IsThumbnail( ) )
+            { // delete the file
+            DeleteFileL( resBn->Path( ) );
+            }
+
+        // clean up 
+        CleanupStack::PopAndDestroy( resBn );
+
+        // delete the row
+        table.DeleteL( );
+        }
+    // clean up
+    CleanupStack::PopAndDestroy( &table );
+
+    }
+//
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::DeleteObjectsL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+void CUpnpMetadataStorage::DeleteObjectsL( TInt aObjId )
+    {
+    RDbTable table;
+    CleanupClosePushL( table );
+    TDbSeekKey seekKey(aObjId);
+    User::LeaveIfError( table.Open( iDatabase, KObjectTableName,
+        table.EUpdatable ) );
+    User::LeaveIfError( table.SetIndex( KObjIdIndexName ) ); // use index
+    if ( table.SeekL( seekKey ) ) // find object
+        { // object found
+        table.GetL( );
+
+        // delete the row
+        table.DeleteL( );
+        }
+    CleanupStack::PopAndDestroy( &table );
+    }
+//
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::DeleteReferencesL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+void CUpnpMetadataStorage::DeleteReferencesL( TInt aObjId,
+    RArray<TInt>& aRefList )
+    {
+    RDbTable table;
+    TInt ret( KErrNotFound );
+    CleanupClosePushL( table );
+    TDbSeekKey seekKey(aObjId);
+    User::LeaveIfError( table.Open( iDatabase, KObjectTableName,
+        table.EUpdatable ) );
+    User::LeaveIfError( table.SetIndex( KRefIdIndexName ) ); // use index
+    while ( table.SeekL( seekKey ) ) // find object
+        { // object found
+        table.GetL( );
+        CDbColSet* colSet = table.ColSetL( );
+        CleanupStack::PushL( colSet );
+        TDbColNo colNo(colSet->ColNo( KObjParentIdColName ) );
+        ret = table.ColInt( colNo );
+        aRefList.Append( ret );
+        CleanupStack::PopAndDestroy( colSet );
+        // delete the row
+        table.DeleteL( );
+        }
+    CleanupStack::PopAndDestroy( &table );
+    }
+//
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::DeleteElementsL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+void CUpnpMetadataStorage::DeleteElementsL( TInt aObjId )
+    {
+    RDbTable table;
+    CleanupClosePushL( table );
+    TDbSeekKey seekKey(aObjId);
+    User::LeaveIfError( table.Open( iDatabase, KElementTableName,
+        table.EUpdatable ) );
+    User::LeaveIfError( table.SetIndex( KElmObjIdIndexName ) ); // use index
+    while ( table.SeekL( seekKey ) ) // find object
+        { // object found
+        table.GetL( );
+
+        // delete the row
+        table.DeleteL( );
+        }
+    CleanupStack::PopAndDestroy( &table );
+    }
+//
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::DeleteAttributesL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+void CUpnpMetadataStorage::DeleteAttributesL( TInt aObjId )
+    {
+    RDbTable table;
+    CleanupClosePushL( table );
+    TDbSeekKey seekKey(aObjId);
+    User::LeaveIfError( table.Open( iDatabase, KAttributeTableName,
+        table.EUpdatable ) );
+    User::LeaveIfError( table.SetIndex( KAtrElmIdIndexName ) ); // use index
+    while ( table.SeekL( seekKey ) ) // find object
+        { // object found
+        table.GetL( );
+
+        // delete the row
+        table.DeleteL( );
+        }
+    CleanupStack::PopAndDestroy( &table );
+    }
+//
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::GetColDesValFromRowSetL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+HBufC8* CUpnpMetadataStorage::GetColDesValFromRowSetL( RDbRowSet aRowset,
+    TDbColNo aColNo )
+    {
+    TDbColType colType = aRowset.ColType( aColNo );
+    TBuf8<KMaxIntegerLen> val;
+    switch ( colType )
+        // so far only 2 types are possible
+        {
+        case EDbColBit:
+            val.Num( aRowset.ColUint8( aColNo ) );
+            break;
+        case EDbColInt32:
+        case EDbColInt16:
+        case EDbColInt8:
+            val.Num( aRowset.ColInt( aColNo ) );
+            break;
+        default:
+            User::Leave( KErrGeneral );
+        }
+    return val.AllocL( );
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::DeleteFileL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::DeleteFileL( const TDesC& aPath )
+    {
+    iFsSession.Delete( aPath );
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::InsertIntoObjectTableL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpMetadataStorage::InsertIntoObjectTableL( TInt aContainerId,
+    CUpnpObjectBean* aObjBn )
+    {
+    // open table
+    RDbTable table;
+    User::LeaveIfError( table.Open( iDatabase, KObjectTableName,
+        table.EUpdatable ) );
+    CleanupClosePushL( table );
+
+    // CdbColSet
+    CDbColSet* objColSet = table.ColSetL( );
+    CleanupStack::PushL( objColSet );
+
+    // rowset cursor to the beginning position
+    table.Reset( );
+
+    // insert empty row
+    table.InsertL( );
+
+    // object id
+    TInt objId = GetNextKeyL( KObjectTableName8 );
+    table.SetColL( objColSet->ColNo( KObjIdColName ), objId );
+
+    // parent id
+    table.SetColL( objColSet->ColNo( KObjParentIdColName ), aContainerId );
+
+    // restricted
+    table.SetColL( objColSet->ColNo( KObjRestrictedColName ),
+        aObjBn->ObjRestricted( ) );
+
+    // set title
+    table.SetColL( objColSet->ColNo( KObjTiltleColName ), aObjBn->ObjTitle( ) );
+
+    // set class
+    table.SetColL( objColSet->ColNo( KObjClassColName ), aObjBn->ObjClass( ) );
+
+    table.SetColL( objColSet->ColNo( KObjRefIdColName ), aObjBn->ObjRefId( ) );
+    // set path
+    HBufC8* path = CreatePathValL( aContainerId );
+    CleanupStack::PushL( path );
+    table.SetColL( objColSet->ColNo( KObjPathColName ), *path );
+
+    // complete insertion
+    table.PutL( );
+
+    DbChangedL( KExecuteWeight );
+
+    // clean up
+    CleanupStack::PopAndDestroy( path );
+    CleanupStack::PopAndDestroy( objColSet );
+    CleanupStack::PopAndDestroy( &table );
+
+    return objId;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::InsertIntoElementTableL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpMetadataStorage::InsertIntoElementTableL( TInt aObjId,
+    CUpnpElementBean* aElmBn, TInt aElmId )
+    {
+    // open table
+    RDbTable table;
+    User::LeaveIfError( table.Open( iDatabase, KElementTableName,
+        table.EUpdatable ) );
+    CleanupClosePushL( table );
+
+    // CdbColSet
+    CDbColSet* objColSet = table.ColSetL( );
+    CleanupStack::PushL( objColSet );
+
+    // rowset cursor to the beginning position
+    table.Reset( );
+
+    // insert empty row
+    table.InsertL( );
+
+    // elm_id
+    table.SetColL( objColSet->ColNo( KElmIdColName ), aElmId );
+
+    // elm_name
+    table.SetColL( objColSet->ColNo( KElmNameColName ), aElmBn->ElmName( ) );
+
+    // elm_value
+    if ( aElmBn->ElmValue().Length( ) )
+        {
+        // use write stream
+        RDbColWriteStream ws;
+        ws.OpenLC( table, objColSet->ColNo( KElmValueColName ) );
+        ws.WriteL( aElmBn->ElmValue( ) ); // write value
+        ws.CommitL( );
+        CleanupStack::PopAndDestroy( &ws );
+        }
+
+    // elm_has_attribute
+    table.SetColL( objColSet->ColNo( KElmHasAttrColName ),
+        aElmBn->ElmHasAttribute( ) );
+
+    // elm_obj_id
+    table.SetColL( objColSet->ColNo( KElmObjIdColName ), aObjId );
+
+    // elm_is_required
+    table.SetColL( objColSet->ColNo( KElmIsRequiredColName ),
+        aElmBn->ElmIsRequired( ) );
+
+    // complete insertion
+    table.PutL( );
+
+    DbChangedL( KExecuteWeight );
+
+    // clean up
+    CleanupStack::PopAndDestroy( objColSet );
+    CleanupStack::PopAndDestroy( &table );
+
+    return aElmId;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::InsertIntoAttributeTableL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::InsertIntoAttributeTableL( TInt aElmId,
+    CUpnpAttributeBean* aAtrBn, TInt aObjId, TInt aAtrId )
+    {
+    // open table
+    RDbTable table;
+    User::LeaveIfError( table.Open( iDatabase, KAttributeTableName,
+        table.EUpdatable ) );
+    CleanupClosePushL( table );
+
+    // CdbColSet
+    CDbColSet* objColSet = table.ColSetL( );
+    CleanupStack::PushL( objColSet );
+
+    // rowset cursor to the beginning position
+    table.Reset( );
+
+    // insert empty row
+    table.InsertL( );
+
+    // atr_id
+    table.SetColL( objColSet->ColNo( KAtrIdColName ), aAtrId ); // leaves if error
+
+    // atr_name
+    table.SetColL( objColSet->ColNo( KAtrNameColName ), aAtrBn->AtrName( ) ); // name cannot be null
+
+    // atr_value
+    if ( aAtrBn->AtrValue().Length( ) )
+        {
+        // use write stream
+        RDbColWriteStream ws;
+        ws.OpenLC( table, objColSet->ColNo( KAtrValueColName ) );
+        ws.WriteL( aAtrBn->AtrValue( ) ); // write value
+        ws.CommitL( );
+        CleanupStack::PopAndDestroy( &ws );
+        }
+
+    // atr_elm_id
+    table.SetColL( objColSet->ColNo( KAtrElmIdColName ), aElmId );
+
+    // atr_is_required
+    table.SetColL( objColSet->ColNo( KAtrIsRequiredColName ),
+        aAtrBn->AtrIsRequired( ) );
+
+    // atr_obj_id
+    table.SetColL( objColSet->ColNo( KAtrIdObjColName ), aObjId );
+
+    // complete insertion
+    table.PutL( );
+
+    DbChangedL( KExecuteWeight );
+
+    // clean up
+    CleanupStack::PopAndDestroy( objColSet );
+    CleanupStack::PopAndDestroy( &table );
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::DeleteObjectL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpMetadataStorage::DeleteObjectL( TInt aObjId,
+    RArray<TInt>& aRefList, TBool aDeleteResource, TBool aLocal,
+    TBool aDeleteRef )
+    {
+    TUpnpErrorCode ret = ENoSuchObject;
+
+    // start transaction
+    BeginTransactionL( );
+
+    RArray<TInt> resList;
+    CleanupClosePushL( resList );
+    TInt delNumber = NULL;
+    TRAPD( err, delNumber = DoDeleteObjectL( aObjId, aRefList, resList,
+        aDeleteResource, aLocal, aDeleteRef ) );
+    if ( err )
+        { // rollback - error
+        RollbackTransactionL( );
+        User::Leave( err );
+        }
+    // commit if success
+    CommitTransactionL( );
+
+    // everything went OK, delete files
+    DeleteResourcesL( resList );
+
+    // clean up
+    CleanupStack::PopAndDestroy( &resList );
+
+    if ( delNumber )
+        {
+        ret = EUpnpOk;
+        }
+
+    return ret;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::DoDeleteObjectL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpMetadataStorage::DoDeleteObjectL( TInt aObjId,
+    TBool aDeleteResource, TBool aDeleteRef )
+    {
+    TUpnpErrorCode ret = ENoSuchObject;
+    RArray<TInt> ignore;
+    CleanupClosePushL( ignore );
+    if ( DoDeleteObjectL( aObjId, ignore, ignore, aDeleteResource, EFalse,
+        aDeleteRef ) )
+        {
+        ret = EUpnpOk;
+        }
+    CleanupStack::PopAndDestroy( &ignore );
+    return ret;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::DoDeleteObjectL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpMetadataStorage::DoDeleteObjectL( TInt aObjId,
+    RArray<TInt>& aRefList, RArray<TInt>& aResList, TBool aDeleteResource,
+    TBool aLocal, TBool aDeleteRef )
+    {
+    TInt numberDeleted = NULL;
+    RArray<TInt> objList;
+    CleanupClosePushL( objList );
+
+    // prepare list of object and resources in the object to be deleted
+    if ( aDeleteResource )
+        {
+        AddSubObjectsL( aObjId, objList, aResList, aLocal );
+        }
+    else
+        {
+        objList.AppendL( aObjId );
+        }
+
+    // error if nothing can be deleted
+    if ( !objList.Count( ) )
+        {
+        User::Leave( ERestrictedObject );
+        }
+
+    // delete each object
+    for ( TInt i = 0; i < objList.Count( ); i++ )
+        {
+        DeleteObjectsL( objList[i] );
+        DeleteElementsL( objList[i] );
+        DeleteAttributesL( objList[i] );
+        if ( aDeleteRef )
+            {
+            DeleteReferencesL( objList[i], aRefList );
+            }
+
+        numberDeleted++;
+        }
+    CleanupStack::PopAndDestroy( &objList );
+
+    return numberDeleted;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::DeleteResourcesL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::DeleteResourcesL( RArray<TInt>& aObjList )
+    {
+    for ( TInt i = 0; i < aObjList.Count( ); i++ )
+        {
+        DeleteResourceByObjIdL( aObjList[i] );
+        }
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::AddSubObjectsL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpMetadataStorage::AddSubObjectsL( TInt aObjId,
+    RArray<TInt>& aObjList, RArray<TInt>& aResList, TBool aLocal )
+    {
+    // number of restricted objects in the subtree 
+    TInt mustRemain = 0;
+
+    // direct children
+    RArray<TInt> children;
+    CleanupClosePushL( children );
+    GetObjectListL( aObjId, children );
+
+    // for each children
+    for ( TInt i = 0; i < children.Count( ); i++ )
+        {
+        // next level
+        mustRemain
+                += AddSubObjectsL( children[i], aObjList, aResList, aLocal );
+        }
+
+    // clean up
+    CleanupStack::PopAndDestroy( &children );
+
+    if ( !aLocal ) // local api can delete even restricted objects
+        {
+        // restricted?
+        if ( CheckObjectRestrictionL( aObjId ) == ERestrictedObject )
+            {
+            mustRemain++;
+            }
+
+        // restricted parent?
+        if ( CheckParentRestrictionL( aObjId ) == ERestrictedObject )
+            {
+            mustRemain++;
+            }
+        }
+
+    // can be deleted?
+    if ( !mustRemain )
+        { // delete the object
+        // add currrent object
+        aObjList.AppendL( aObjId );
+        aResList.AppendL( aObjId );
+        }
+    return mustRemain;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::CheckParentRestrictionL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpMetadataStorage::CheckParentRestrictionL( TInt aObjId )
+    {
+    TInt parentId = GetParentIdL( aObjId );
+    return CheckObjectRestrictionL( parentId );
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::AddResourceL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::AddResourceL( CUpnpResourcesBean* aResBean,
+    TInt aObjId )
+    {
+    HBufC* resValReplaced16 = UpnpCdUtils::EscapeAposL( aResBean->Path( ) );
+
+    // prepare command
+    HBufC* sqlCommand = HBufC::NewLC( KInsertInto().Length( ) 
+                                      + KResourcesTableName().Length( ) 
+                                      + KOpenParant().Length( ) 
+                                      + KRscIdColName().Length( ) 
+                                      + KRscPathColName().Length( ) 
+                                      + KRscReadonlyColName().Length( ) 
+                                      + KRscThumbnailColName().Length( ) 
+                                      + KRscIdObjColName().Length( ) 
+                                      + KCloseParant().Length( ) 
+                                      + KValuesOpen().Length( ) 
+                                      + KMaxIntegerLen 
+                                      + resValReplaced16->Des().Length( ) 
+                                      + KMaxBoolLen 
+                                      + KMaxBoolLen 
+                                      + KMaxLongIntegerLen
+                                      + KCloseParant().Length( )  
+                                      + 2 * KQuot().Length( ) 
+                                      + 8 * KCommaStr().Length( ) ); // we need 4 commas and 2 quotation-marks
+
+    TPtr sqlCmdPtr(sqlCommand->Des( ));
+
+    TBuf<KMaxIntegerLen> num;
+    TBuf<KMaxLongIntegerLen> numLong;
+
+    sqlCmdPtr.Append( KInsertInto );
+    sqlCmdPtr.Append( KResourcesTableName );
+    sqlCmdPtr.Append( KOpenParant );
+    sqlCmdPtr.Append( KRscIdColName );
+    sqlCmdPtr.Append( KCommaStr );
+    sqlCmdPtr.Append( KRscPathColName );
+    sqlCmdPtr.Append( KCommaStr );
+    sqlCmdPtr.Append( KRscReadonlyColName );
+    sqlCmdPtr.Append( KCommaStr );
+    sqlCmdPtr.Append( KRscThumbnailColName );
+    sqlCmdPtr.Append( KCommaStr );
+    sqlCmdPtr.Append( KRscIdObjColName );
+    sqlCmdPtr.Append( KCloseParant );
+    sqlCmdPtr.Append( KValuesOpen );
+    numLong.Num( aResBean->Id( ) );
+    sqlCmdPtr.Append( numLong );
+    sqlCmdPtr.Append( KCommaStr );
+    sqlCmdPtr.Append( KQuot );
+    sqlCmdPtr.Append( *resValReplaced16 );
+    sqlCmdPtr.Append( KQuot );
+    sqlCmdPtr.Append( KCommaStr );
+    num.Num( aResBean->IsReadonly( ) );
+    sqlCmdPtr.Append( num );
+    sqlCmdPtr.Append( KCommaStr );
+    num.Num( aResBean->IsThumbnail( ) );
+    sqlCmdPtr.Append( num );
+    sqlCmdPtr.Append( KCommaStr );
+    num.Num( aObjId );
+    sqlCmdPtr.Append( num );
+    sqlCmdPtr.Append( KCloseParant );
+
+    delete resValReplaced16;
+    // execute
+    ExecuteL( sqlCmdPtr );
+    // clean up
+    CleanupStack::PopAndDestroy( sqlCommand );
+
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::RecoverDatabase
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpMetadataStorage::RecoverDatabase()
+    {
+    return iDatabase.Recover( );
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::RecreateDatabaseFileL
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::RecreateDatabaseFileL()
+    {
+    iDatabase.Close( );
+    iIsOpen = EFalse;
+
+    delete iFileStore;
+    iFileStore = NULL;
+
+    CUpnpCdDbFactory* cdf = CUpnpCdDbFactory::NewLC( );
+
+    // database file name
+    RFs fs;
+    CleanupClosePushL( fs );
+    User::LeaveIfError( fs.Connect( ) );
+
+    TFileName path;
+    User::LeaveIfError( fs.PrivatePath( path ) );
+    TParse fp;
+    fp.Set( KDatabaseFileName( ), &path, 0 );
+    path = fp.FullName( );
+
+    // recreate database file
+    cdf->CreateDatabaseFileL( path );
+
+    CleanupStack::PopAndDestroy( &fs );
+    CleanupStack::PopAndDestroy( cdf );
+
+    OpenDbL( path );
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::CompareDbColSetsL
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::CompareDbColSetsL( CDbColSet *aColSet1,
+    CDbColSet *aColSet2 )
+    {
+    if ( !aColSet1 || !aColSet1 )
+        User::Leave( KErrCorrupt );
+    if ( aColSet1->Count( ) != aColSet1->Count( ) )
+        User::Leave( KErrCorrupt );
+
+    for ( TInt i=1; i<=aColSet1->Count( ); i++ )
+        {
+        TBool foundColumn = EFalse;
+        const TDbCol& col1 = (*aColSet1)[i];
+
+        for ( TInt j=1; j<=aColSet2->Count( ); j++ )
+            {
+            const TDbCol& col2 = (*aColSet2)[j];
+            TInt cmpResult = col1.iName.Compare( col2.iName );
+
+            if ( cmpResult == 0 && !foundColumn )
+                {
+                foundColumn = ETrue;
+                if ( col1.iType != col2.iType )
+                    User::Leave( KErrCorrupt );
+                if ( !col1.IsLong( col1.iType ) && col1.iMaxLength
+                        != col2.iMaxLength )
+                    User::Leave( KErrCorrupt );
+                if ( col1.iAttributes != col2.iAttributes )
+                    User::Leave( KErrCorrupt );
+                }
+            else if ( cmpResult == 0 && foundColumn )
+                User::Leave( KErrCorrupt );
+            }
+        if ( !foundColumn )
+            User::Leave( KErrCorrupt );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::CheckDatabaseL
+// -----------------------------------------------------------------------------
+//
+void CUpnpMetadataStorage::CheckDatabaseL()
+    {
+    CDbTableNames *tableNames = iDatabase.TableNamesL( );
+    CleanupStack::PushL( tableNames );
+
+    if ( !tableNames )
+        User::Leave( KErrCorrupt );
+    CUpnpCdDbFactory* cdf = CUpnpCdDbFactory::NewLC( );
+
+    for ( TInt i=0; i<tableNames->Count( ); i++ )
+        {
+        CDbColSet *colSetRef = NULL;
+
+        if ( (*tableNames)[i].Compare( KObjectTableName ) == 0 )
+            {
+            colSetRef = cdf->CreateObjectTableColumnSequenceLC( );
+            }
+        else if ( (*tableNames)[i].Compare( KElementTableName ) == 0 )
+            {
+            colSetRef = cdf->CreateElementTableColumnSequenceLC( );
+            }
+        else if ( (*tableNames)[i].Compare( KAttributeTableName ) == 0 )
+            {
+            colSetRef = cdf->CreateAttributeTableColumnSequenceLC( );
+            }
+        else if ( (*tableNames)[i].Compare( KResourcesTableName ) == 0 )
+            {
+            colSetRef = cdf->CreateResourceTableColumnSequenceLC( );
+            }
+        else if ( (*tableNames)[i].Compare( KSequencesTableName ) == 0 )
+            {
+            colSetRef = cdf->CreateSequenceTableColumnSequenceLC( );
+            }
+        else
+            User::Leave( KErrCorrupt );
+
+        CDbColSet *colSet = iDatabase.ColSetL( (*tableNames)[i] );
+        CleanupStack::PushL( colSet );
+
+        CompareDbColSetsL( colSet, colSetRef );
+
+        CleanupStack::PopAndDestroy( colSet );
+        CleanupStack::PopAndDestroy( colSetRef );
+        }
+
+    CleanupStack::PopAndDestroy( cdf );
+    CleanupStack::PopAndDestroy( tableNames );
+    }
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::HandleDbError
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpMetadataStorage::HandleDbError( TInt aError )
+    {
+    TInt err = aError;
+    if ( err == KErrCorrupt )
+        {
+        if ( iIsOpen )
+            {
+            err = RecoverDatabase( );
+            }
+        if ( err!=KErrNone && err!=KErrDiskFull && err!=KErrNoMemory )
+            {
+            TRAP( err, RecreateDatabaseFileL( ) );
+            if ( err )
+                {
+                iIsOpen = EFalse;
+                err = KErrCorrupt;
+                }
+            else
+                {
+                iIsOpen = ETrue;
+                }
+            }
+        }
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpMetadataStorage::IsDbCreated
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpMetadataStorage::IsDbCreated()
+    {
+    return iIsOpen;
+    }
+
+//  End of File