mpxplugins/serviceplugins/collectionplugins/mpxsqlitedbcommon/src/mpxdbmanager.cpp
changeset 0 ff3acec5bc43
child 11 13afc0e517bd
equal deleted inserted replaced
-1:000000000000 0:ff3acec5bc43
       
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  This class is responsible for managing all database access
       
    15 *                databases.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 
       
    22 #include <sqldb.h>
       
    23 #include <badesca.h>
       
    24 #include <f32file.h>
       
    25 // PREQ2536 the files sqlrowsetutil.h and sqlrowsetutil.cpp has been removed
       
    26 //#ifdef __WINSCW__    
       
    27 //#include <sqlrowsetutil.h>
       
    28 //#endif
       
    29 #include <sysutil.h>
       
    30 
       
    31 #include <mpxlog.h>
       
    32 
       
    33 #include "mpxdbcommondef.h"
       
    34 #include "mpxtable.h"
       
    35 #include "mpxdbmanager.h"
       
    36 
       
    37 // CONSTANTS
       
    38 
       
    39 // Version of   Database
       
    40 const   TInt KMPXDbVersion[] = {6,0,0};
       
    41 
       
    42 _LIT8( KMCSqlConfig, "cache_size=1024; page_size=16384; " );
       
    43 
       
    44 _LIT(KSecureFilePath,   "%S[%x]%S");
       
    45 _LIT(KRootDrive, "C:");
       
    46 _LIT(KAliasName, "%1SDrive");
       
    47 _LIT(KBeginTransaction, "BEGIN TRANSACTION");
       
    48 _LIT(KCommitTransaction, "COMMIT TRANSACTION");
       
    49 _LIT(KRollbackTransaction, "ROLLBACK TRANSACTION");
       
    50 _LIT(KOrderByToken, "ORDER BY");
       
    51 _LIT(KDBNameToken, ":dbname");
       
    52 _LIT(KPlDBNameToken, ":pldbname");
       
    53 _LIT(KUnionAllToken, " UNION ALL ");
       
    54 _LIT(KSelectToken, "SELECT");
       
    55 
       
    56 //for database deletion
       
    57 _LIT( KDBFilePath, "\\private\\10281e17\\" );
       
    58 _LIT( KDBFilePattern, "*.db*" );    
       
    59 
       
    60 #ifdef _DEBUG
       
    61 _LIT(KTableQuery, "SELECT * FROM %S");
       
    62 _LIT(KAttachedTableQuery, "SELECT * FROM :dbname.%S");
       
    63 _LIT(KFindAllCDriveTablesQuery, "SELECT name FROM   sqlite_master WHERE type = 'table' ORDER BY name");
       
    64 _LIT(KFindAllAttachedTablesQuery, "SELECT name FROM :dbname.sqlite_master WHERE type = 'table' ORDER BY name");
       
    65 _LIT(KNameColumn, "name");
       
    66 #endif
       
    67 
       
    68 const TInt KMaxLogQuery = 248;
       
    69 const TInt KBufIncrement = 10;
       
    70 
       
    71 // Used to suppress overflow when appending formatted text to a buffer.
       
    72 class TOverflowHandle :
       
    73     public TDesOverflow
       
    74     {
       
    75     public:
       
    76         TOverflowHandle() :
       
    77             iFlag(EFalse)
       
    78             {
       
    79             }
       
    80 
       
    81         virtual void Overflow(TDes& /* aDes */)
       
    82             {
       
    83             iFlag = ETrue;
       
    84             return;
       
    85             }
       
    86 
       
    87         TBool GetOverflowFlag()
       
    88             {
       
    89             TBool flag(iFlag);
       
    90             iFlag = EFalse;
       
    91             return flag;
       
    92             }
       
    93     protected:
       
    94         TBool iFlag;
       
    95     };
       
    96 
       
    97 // ============================ MEMBER FUNCTIONS ==============================
       
    98 
       
    99 // ----------------------------------------------------------------------------
       
   100 // Constructor
       
   101 // ----------------------------------------------------------------------------
       
   102 //
       
   103 EXPORT_C CMPXDbManager::CMPXDbManager(
       
   104     RFs& aFs) :
       
   105     iFs(aFs)
       
   106     {
       
   107     MPX_FUNC("CMPXDbManager::CMPXDbManager");
       
   108     }
       
   109 
       
   110 // ----------------------------------------------------------------------------
       
   111 // Second phase constructor.
       
   112 // ----------------------------------------------------------------------------
       
   113 //
       
   114 EXPORT_C void CMPXDbManager::ConstructL(
       
   115     const TFileName& aDatabaseFile)
       
   116     {
       
   117     MPX_FUNC("CMPXDbManager::ConstructL");
       
   118     iDbFile = aDatabaseFile.AllocL();
       
   119     }
       
   120 
       
   121 // ----------------------------------------------------------------------------
       
   122 // Destructor
       
   123 // ----------------------------------------------------------------------------
       
   124 //
       
   125 EXPORT_C CMPXDbManager::~CMPXDbManager()
       
   126     {
       
   127     MPX_FUNC("CMPXDbManager::~CMPXDbManager");
       
   128 
       
   129     // Close the state array
       
   130     iPreparedStatements.Close();
       
   131 
       
   132     // Close and destroy all RSQLStatements
       
   133     TInt c( iStatements.Count() );
       
   134     for( TInt i=0; i<c; ++i )
       
   135         {
       
   136         iStatements[i]->Close();
       
   137         }
       
   138     iStatements.ResetAndDestroy();
       
   139 
       
   140     iTables.Close();
       
   141     CloseAllDatabases();
       
   142 
       
   143     delete iDbFile;
       
   144     }
       
   145 
       
   146 // ----------------------------------------------------------------------------
       
   147 // Checks if all databases have been initialized.
       
   148 // ----------------------------------------------------------------------------
       
   149 //
       
   150 EXPORT_C TBool CMPXDbManager::IsInitialized()
       
   151     {
       
   152     MPX_FUNC("CMPXDbManager::IsInitialized");
       
   153     return iInitialized;
       
   154     }
       
   155 
       
   156 // ----------------------------------------------------------------------------
       
   157 // Begins a transaction on all databases.
       
   158 // ----------------------------------------------------------------------------
       
   159 //
       
   160 EXPORT_C void CMPXDbManager::BeginL()
       
   161     {
       
   162     MPX_FUNC("CMPXDbManager::BeginL");
       
   163 
       
   164     ASSERT(iTransactionCount >= 0);
       
   165 
       
   166     if (++iTransactionCount == 1)
       
   167         {
       
   168         TInt err = iDatabase.Exec(KBeginTransaction);
       
   169         
       
   170         // transforms SQL error to KErrNotReady
       
   171         if( (err <= KSqlErrGeneral && err >= KSqlErrNotDb) || err == KSqlErrStmtExpired )
       
   172             {
       
   173             User::Leave(KErrNotReady);
       
   174             }
       
   175         else
       
   176             {
       
   177             User::LeaveIfError(err);
       
   178             }
       
   179         }
       
   180     }
       
   181 
       
   182 // ----------------------------------------------------------------------------
       
   183 // Commits a transaction on all databases.
       
   184 // ----------------------------------------------------------------------------
       
   185 //
       
   186 EXPORT_C void CMPXDbManager::CommitL()
       
   187     {
       
   188     MPX_FUNC("CMPXDbManager::CommitL");
       
   189 
       
   190     if(iTransactionCount > 0)
       
   191         {
       
   192         if (--iTransactionCount == 0)
       
   193             {
       
   194             TInt err = iDatabase.Exec(KCommitTransaction);
       
   195             
       
   196             // transforms SQL error to KErrNotReady
       
   197             if( (err <= KSqlErrGeneral && err >= KSqlErrNotDb) || err == KSqlErrStmtExpired )
       
   198                 {
       
   199                 User::Leave(KErrNotReady);
       
   200                 }
       
   201             else
       
   202                 {
       
   203                 User::LeaveIfError(err);
       
   204                 }
       
   205             }
       
   206         }
       
   207     }
       
   208 
       
   209 // ----------------------------------------------------------------------------
       
   210 // Rolls back a transaction on all databases.
       
   211 // ----------------------------------------------------------------------------
       
   212 //
       
   213 EXPORT_C void CMPXDbManager::RollbackL()
       
   214     {
       
   215     MPX_FUNC("CMPXDbManager::RollbackL");
       
   216 
       
   217     if(iTransactionCount > 0)
       
   218         {
       
   219         if (--iTransactionCount == 0)
       
   220             {
       
   221             TInt err = iDatabase.Exec(KRollbackTransaction);
       
   222             
       
   223             // transforms SQL error to KErrNotReady
       
   224             if( (err <= KSqlErrGeneral && err >= KSqlErrNotDb) || err == KSqlErrStmtExpired )
       
   225                 {
       
   226                 User::Leave(KErrNotReady);  
       
   227                 }
       
   228             else
       
   229                 {
       
   230                 User::LeaveIfError(err);
       
   231                 }
       
   232             }
       
   233     	}
       
   234     }
       
   235 
       
   236 // ----------------------------------------------------------------------------
       
   237 // Rolls back a transaction on all databases.
       
   238 // ----------------------------------------------------------------------------
       
   239 //
       
   240 EXPORT_C TBool CMPXDbManager::InTransaction()
       
   241     {
       
   242     MPX_FUNC("CMPXDbManager::InTransaction");
       
   243     return iDatabase.InTransaction();
       
   244     }
       
   245 
       
   246 // ----------------------------------------------------------------------------
       
   247 // Tries to create and open the databases on all specified drives.
       
   248 // ----------------------------------------------------------------------------
       
   249 //
       
   250 EXPORT_C void CMPXDbManager::InitDatabasesL(
       
   251     RArray<TInt> aDrives)
       
   252     {
       
   253     MPX_FUNC("CMPXDbManager::InitDatabasesL");
       
   254 
       
   255     CloseAllDatabases();
       
   256 
       
   257     TDriveUnit cdrive(KRootDrive());
       
   258 
       
   259     CreateDatabaseL(cdrive);
       
   260     OpenDatabaseL(cdrive);
       
   261 
       
   262     TInt count(aDrives.Count());
       
   263     for (TInt i = 0; i < count; ++i)
       
   264         {
       
   265         TDriveUnit drive(aDrives[i]);
       
   266         if ((drive != cdrive) && !IsRemoteDrive(static_cast<TDriveNumber>(aDrives[i])))
       
   267             {
       
   268             const TDesC& driveName = drive.Name();
       
   269 
       
   270             DatabaseHandle handle;
       
   271 
       
   272             handle.iDrive = aDrives[i];
       
   273             handle.iAliasname = HBufC::NewL(KAliasName().Length());
       
   274             handle.iAliasname->Des().Format(KAliasName, &driveName);
       
   275             handle.iOpen = EFalse;
       
   276 
       
   277             iDatabaseHandles.AppendL(handle);
       
   278 
       
   279             TVolumeInfo vol;
       
   280             if (iFs.Volume(vol, drive) == KErrNone)
       
   281                 {
       
   282                 CreateDatabaseL(drive);
       
   283                 AttachDatabaseL(drive);
       
   284                 }
       
   285             }
       
   286         }
       
   287 
       
   288     iInitialized = ETrue;
       
   289     }
       
   290 
       
   291 // ----------------------------------------------------------------------------
       
   292 // Opens a specified database.
       
   293 // ----------------------------------------------------------------------------
       
   294 //
       
   295 EXPORT_C void CMPXDbManager::OpenDatabaseL(
       
   296     TInt aDrive)
       
   297     {
       
   298     MPX_FUNC("CMPXDbManager::OpenDatabaseL");
       
   299 
       
   300     if (iInitialized == EFalse)
       
   301         {
       
   302         User::Leave(KErrNotReady);
       
   303         }
       
   304 
       
   305     TDriveUnit drive(aDrive);
       
   306     TDriveUnit cdrive(KRootDrive());
       
   307     TBool found(EFalse);
       
   308 
       
   309     if ((drive != cdrive) && !IsRemoteDrive(static_cast<TDriveNumber>(aDrive)))
       
   310         {
       
   311         TInt count(iDatabaseHandles.Count());
       
   312         for (TInt i = 0; i < count; ++i)
       
   313             {
       
   314             if (iDatabaseHandles[i].iDrive == aDrive)
       
   315                 {
       
   316                 if (!iDatabaseHandles[i].iOpen)
       
   317                     {
       
   318                     // make sure the database is created
       
   319 					CreateDatabaseL(drive);
       
   320 
       
   321 					// attach
       
   322                     AttachDatabaseL(drive);
       
   323                     }
       
   324 
       
   325                 found = ETrue;
       
   326                 break;
       
   327                 }
       
   328             }
       
   329         }
       
   330     if (!found)
       
   331         {
       
   332         User::Leave(KErrArgument);
       
   333         }
       
   334 
       
   335     // Close all prepared statements if a db is opened
       
   336     //
       
   337     ResetPreparedQueries();
       
   338     }
       
   339 
       
   340 // ----------------------------------------------------------------------------
       
   341 // Closes a specified database.
       
   342 // ----------------------------------------------------------------------------
       
   343 //
       
   344 EXPORT_C void CMPXDbManager::CloseDatabaseL(
       
   345     TInt aDrive)
       
   346     {
       
   347     MPX_FUNC("CMPXDbManager::CloseDatabaseL");
       
   348 
       
   349     if (iInitialized == EFalse)
       
   350         {
       
   351         User::Leave(KErrNotReady);
       
   352         }
       
   353 
       
   354     // Close all prepared statements if a db is closed
       
   355     //
       
   356     ResetPreparedQueries();
       
   357 
       
   358     TDriveUnit drive(aDrive);
       
   359     TDriveUnit cdrive(KRootDrive());
       
   360     TBool found(EFalse);
       
   361 
       
   362     if ((drive != cdrive) && !IsRemoteDrive(static_cast<TDriveNumber>(aDrive)))
       
   363         {
       
   364         TInt count(iDatabaseHandles.Count());
       
   365         for (TInt i = 0; i < count; ++i)
       
   366             {
       
   367             if (iDatabaseHandles[i].iDrive == aDrive)
       
   368                 {
       
   369                 if (iDatabaseHandles[i].iOpen)
       
   370                     {
       
   371                     DetachDatabaseL(drive);
       
   372                     }
       
   373 
       
   374                 found = ETrue;
       
   375                 break;
       
   376                 }
       
   377             }
       
   378         }
       
   379     if (!found)
       
   380         {
       
   381         User::Leave(KErrArgument);
       
   382         }
       
   383 
       
   384     }
       
   385 
       
   386 // ----------------------------------------------------------------------------
       
   387 // Closes all databases.
       
   388 // ----------------------------------------------------------------------------
       
   389 //
       
   390 EXPORT_C void CMPXDbManager::CloseAllDatabases()
       
   391     {
       
   392     MPX_FUNC("CMPXDbManager::CloseAllDatabases");
       
   393 
       
   394     if (iInitialized)
       
   395         {
       
   396         // Close all prepared statements if a db is closed
       
   397         //
       
   398         ResetPreparedQueries();
       
   399 
       
   400         TInt count(iDatabaseHandles.Count());
       
   401         for (TInt i = 0; i < count; ++i)
       
   402             {
       
   403             delete iDatabaseHandles[i].iAliasname;
       
   404             }
       
   405 
       
   406         iDatabaseHandles.Reset();
       
   407         iDatabase.Close();
       
   408         iInitialized = EFalse;
       
   409         }
       
   410     }
       
   411 
       
   412 // ----------------------------------------------------------------------------
       
   413 // Open all databases.
       
   414 // ----------------------------------------------------------------------------
       
   415 //
       
   416 EXPORT_C void CMPXDbManager::OpenAllDatabasesL()
       
   417     {
       
   418     MPX_FUNC("CMPXDbManager::OpenAllDatabasesL");
       
   419 
       
   420     if (!iInitialized)
       
   421         {
       
   422         TDriveUnit cdrive(KRootDrive());
       
   423         OpenDatabaseL(cdrive);
       
   424         }
       
   425 
       
   426     TInt count(iDatabaseHandles.Count());
       
   427     for (TInt i = 0; i < count; ++i)
       
   428         {
       
   429         TVolumeInfo vol;
       
   430         if (iFs.Volume(vol, iDatabaseHandles[i].iDrive) == KErrNone)
       
   431             {
       
   432             AttachDatabaseL(iDatabaseHandles[i].iDrive);
       
   433             }
       
   434         }
       
   435     iInitialized = ETrue;
       
   436 
       
   437     // Close all prepared statements if a db is closed
       
   438     //
       
   439     ResetPreparedQueries();
       
   440     }
       
   441 
       
   442 // ----------------------------------------------------------------------------
       
   443 // Checks if the database on a specified drive is open.
       
   444 // ----------------------------------------------------------------------------
       
   445 //
       
   446 EXPORT_C TBool CMPXDbManager::IsOpen(
       
   447     TInt aDrive) const
       
   448     {
       
   449     MPX_FUNC("CMPXDbManager::IsOpen");
       
   450 
       
   451     TDriveUnit drive(aDrive);
       
   452     TDriveUnit cdrive(KRootDrive());
       
   453 
       
   454     if (!iInitialized)
       
   455         {
       
   456         return EFalse;
       
   457         }
       
   458     else if (drive == cdrive)
       
   459         {
       
   460         return ETrue;
       
   461         }
       
   462     else
       
   463         {
       
   464         TInt count(iDatabaseHandles.Count());
       
   465         for (TInt i = 0; i < count; ++i)
       
   466             {
       
   467             if (iDatabaseHandles[i].iDrive == aDrive)
       
   468                 {
       
   469                 return iDatabaseHandles[i].iOpen;
       
   470                 }
       
   471             }
       
   472         }
       
   473 
       
   474     return EFalse;
       
   475     }
       
   476 
       
   477 // ----------------------------------------------------------------------------
       
   478 // Returns the number of currently open databases.
       
   479 // ----------------------------------------------------------------------------
       
   480 //
       
   481 EXPORT_C TInt CMPXDbManager::DatabaseCount() const
       
   482     {
       
   483     MPX_FUNC("CMPXDbManager::DatabaseCount");
       
   484 
       
   485     TInt openCount(0);
       
   486     if (iInitialized)
       
   487         {
       
   488         ++openCount;
       
   489 
       
   490         TInt count(iDatabaseHandles.Count());
       
   491         for (TInt i = 0; i < count; ++i)
       
   492             {
       
   493             if (iDatabaseHandles[i].iOpen)
       
   494                 {
       
   495                 ++openCount;
       
   496                 }
       
   497             }
       
   498         }
       
   499 
       
   500     return openCount;
       
   501     }
       
   502 
       
   503 // ----------------------------------------------------------------------------
       
   504 // Returns the drive corresponding to a given index.
       
   505 // ----------------------------------------------------------------------------
       
   506 //
       
   507 EXPORT_C TInt CMPXDbManager::DbDrive(
       
   508     TInt aIndex) const
       
   509     {
       
   510     MPX_FUNC("CMPXDbManager::DbDrive");
       
   511 
       
   512     ASSERT((aIndex >= 0) || (aIndex < iDatabaseHandles.Count()));
       
   513     return iDatabaseHandles[aIndex].iDrive;
       
   514     }
       
   515 
       
   516 // ----------------------------------------------------------------------------
       
   517 // Recreate a specified database.
       
   518 // ----------------------------------------------------------------------------
       
   519 //
       
   520 EXPORT_C void CMPXDbManager::RecreateDatabaseL(
       
   521     TInt aDrive)
       
   522     {
       
   523     MPX_FUNC("CMPXDbManager::RecreateDatabaseL");
       
   524 
       
   525     if (iInitialized == EFalse)
       
   526         {
       
   527         User::Leave(KErrNotReady);
       
   528         }
       
   529 
       
   530     TBool found(EFalse);
       
   531 
       
   532     if (aDrive == EDriveC)
       
   533         {
       
   534         found = ETrue;
       
   535         }
       
   536     else
       
   537         {
       
   538         TInt count(iDatabaseHandles.Count());
       
   539         for (TInt i = 0; i < count; ++i)
       
   540             {
       
   541             if ((iDatabaseHandles[i].iDrive == aDrive) && (iDatabaseHandles[i].iOpen))
       
   542                 {
       
   543                 found = ETrue;
       
   544                 break;
       
   545                 }
       
   546             }
       
   547         }
       
   548     if (found)
       
   549         {
       
   550         HBufC * filename = CreateFilenameL(aDrive);
       
   551         CleanupStack::PushL(filename);
       
   552 
       
   553         TRAPD(err, DoRecreateDatabaseL(filename));
       
   554         if(err < 0)
       
   555             {
       
   556             TDriveUnit drive_unit(aDrive);
       
   557 
       
   558             if(aDrive == EDriveC)
       
   559                 {
       
   560                 iDatabase.Close();
       
   561                 iInitialized = EFalse;
       
   562 
       
   563                 RSqlDatabase::Delete(*filename);
       
   564                 CreateDatabaseL(drive_unit);
       
   565 
       
   566                 User::LeaveIfError(iDatabase.Open(*filename));
       
   567                 iInitialized = ETrue;
       
   568                 }
       
   569             else
       
   570                 {
       
   571                 DetachDatabaseL(drive_unit);
       
   572 
       
   573                 RSqlDatabase::Delete(*filename);
       
   574                 CreateDatabaseL(drive_unit);
       
   575 
       
   576                 AttachDatabaseL(drive_unit);
       
   577                 }
       
   578             }
       
   579 
       
   580         CleanupStack::PopAndDestroy(filename);
       
   581         }
       
   582     else
       
   583         {
       
   584         User::Leave(KErrNotFound);
       
   585         }
       
   586     }
       
   587 
       
   588 // ----------------------------------------------------------------------------
       
   589 // Recreate all databases.
       
   590 // ----------------------------------------------------------------------------
       
   591 //
       
   592 EXPORT_C void CMPXDbManager::RecreateAllDatabasesL()
       
   593     {
       
   594     MPX_FUNC("CMPXDbManager::RecreateAllDatabasesL");
       
   595 
       
   596     if (iInitialized == EFalse)
       
   597         {
       
   598         User::Leave(KErrNotReady);
       
   599         }
       
   600 
       
   601     // Recreate on drive C
       
   602     RecreateDatabaseL(EDriveC);
       
   603 
       
   604     // Recreate all attached drives
       
   605     TInt count(iDatabaseHandles.Count());
       
   606     for (TInt i = 0; i < count; ++i)
       
   607         {
       
   608         if (iDatabaseHandles[i].iOpen)
       
   609             {
       
   610             RecreateDatabaseL(iDatabaseHandles[i].iDrive);
       
   611             }
       
   612         }
       
   613     }
       
   614 
       
   615 // ----------------------------------------------------------------------------
       
   616 // Returns current DB version
       
   617 // ----------------------------------------------------------------------------
       
   618 //
       
   619 EXPORT_C TVersion CMPXDbManager::Version() const
       
   620     {
       
   621     MPX_FUNC("CMPXDbManager::Version");
       
   622     return TVersion(KMPXDbVersion[0], KMPXDbVersion[1], KMPXDbVersion[2]);
       
   623     }
       
   624 
       
   625 // ----------------------------------------------------------------------------
       
   626 // Registes a table with the database
       
   627 // ----------------------------------------------------------------------------
       
   628 //
       
   629 EXPORT_C void CMPXDbManager::RegisterTableL(
       
   630     MMPXTable& aTable)
       
   631     {
       
   632     MPX_FUNC("CMPXDbManager::RegisterTableL");
       
   633     iTables.AppendL(&aTable);
       
   634     }
       
   635 
       
   636 // ----------------------------------------------------------------------------
       
   637 // Executes a select query with variable number of parameters
       
   638 // The query is executed on all available databases with a format like:
       
   639 //
       
   640 //      <query on database1> UNION ALL <query on database2> ...
       
   641 //
       
   642 // The query string passed in by the caller must have the ":dbname" prefix for all
       
   643 // the tables in the FROM clause. This will be replaced with the right alias for
       
   644 // attached databases or with no alias for the C database.
       
   645 //
       
   646 // In case the original query contains an ORDER BY clause, this will be extracted
       
   647 // and added at the end of the union query.
       
   648 //
       
   649 // Note: Running the union query seems to be similar in speed even if one of the
       
   650 // databases is empty and therefore no optimization was done for this case.
       
   651 // ----------------------------------------------------------------------------
       
   652 //
       
   653 EXPORT_C RSqlStatement CMPXDbManager::ExecuteSelectQueryL(
       
   654     TRefByValue<const TDesC> aFmt,
       
   655     ...)
       
   656     {
       
   657     MPX_FUNC("CMPXDatabase::ExecuteSelectQueryL");
       
   658 
       
   659     VA_LIST list;
       
   660     VA_START(list, aFmt);
       
   661 
       
   662     // Will reallocate
       
   663     HBufC* selectBuf = FormatQueryLC(aFmt, list);
       
   664     RSqlStatement statement = ExecuteSelectQueryOnAllDrivesL(selectBuf->Des());
       
   665     CleanupStack::PopAndDestroy(selectBuf);
       
   666 
       
   667     VA_END(list);
       
   668 
       
   669     return statement;
       
   670     }
       
   671 
       
   672 // ----------------------------------------------------------------------------
       
   673 // Executes a select query against a specified drive
       
   674 // ----------------------------------------------------------------------------
       
   675 //
       
   676 EXPORT_C RSqlStatement CMPXDbManager::ExecuteSelectQueryL(
       
   677     TInt aDrive,
       
   678     TRefByValue<const TDesC> aFmt,
       
   679     ...)
       
   680     {
       
   681     MPX_FUNC("CMPXDatabase::ExecuteSelectQueryL");
       
   682 
       
   683     VA_LIST list;
       
   684     VA_START(list, aFmt);
       
   685 
       
   686     // Will reallocate
       
   687     HBufC* selectBuf = FormatQueryLC(aFmt, list);
       
   688     RSqlStatement statement = ExecuteSelectQueryOnDriveL(aDrive, selectBuf->Des());
       
   689     CleanupStack::PopAndDestroy(selectBuf);
       
   690 
       
   691     VA_END(list);
       
   692 
       
   693     return statement;
       
   694     }
       
   695 
       
   696 // ----------------------------------------------------------------------------
       
   697 // CMPXDbManager::ExecuteSelectQueryL
       
   698 // ----------------------------------------------------------------------------
       
   699 //
       
   700 EXPORT_C RSqlStatement& CMPXDbManager::ExecuteSelectQueryL(
       
   701     TUint aStatementId,
       
   702     TInt aFirstValue,
       
   703     TInt aSecondValue,
       
   704     TRefByValue<const TDesC> aFmt,
       
   705     ...)
       
   706     {
       
   707     MPX_FUNC("CMPXDatabase::ExecuteOffsetSelectQueryL");
       
   708 
       
   709     // Prepare the Query first
       
   710     VA_LIST list;
       
   711     VA_START(list, aFmt);
       
   712     RSqlStatement& statement = PrepareQueryL( aStatementId, aFmt, list );
       
   713     VA_END(list);
       
   714 
       
   715     // Bind the Limit and Offset variables
       
   716     User::LeaveIfError(statement.BindInt(0, aFirstValue));
       
   717     User::LeaveIfError(statement.BindInt(1, aSecondValue));
       
   718 
       
   719     return statement;
       
   720     }
       
   721 
       
   722 // ----------------------------------------------------------------------------
       
   723 // CMPXDbManager::ExecuteSelectQueryL
       
   724 // ----------------------------------------------------------------------------
       
   725 //
       
   726 EXPORT_C RSqlStatement& CMPXDbManager::ExecuteSelectQueryL( TUint aStatementId,
       
   727                                                             const TDesC& aFirstValue,
       
   728                                                             TInt aSecondValue,
       
   729                                                             TRefByValue<const TDesC> aFmt, ...)
       
   730     {
       
   731     MPX_FUNC("CMPXDbManager::ExecuteMediaAscQueryL");
       
   732 
       
   733     // Prepare the Query first
       
   734     VA_LIST list;
       
   735     VA_START(list, aFmt);
       
   736     RSqlStatement& statement = PrepareQueryL( aStatementId, aFmt, list );
       
   737     VA_END(list);
       
   738 
       
   739     // bind the title and limit values
       
   740     User::LeaveIfError(statement.BindText(0, aFirstValue));
       
   741     User::LeaveIfError(statement.BindInt(1, aSecondValue));
       
   742 
       
   743     return statement;
       
   744     }
       
   745 
       
   746 // ----------------------------------------------------------------------------
       
   747 // Executes a query that does not return a record set (INSERT, UPDATE, DELETE,
       
   748 // CREATE, DROP, etc).
       
   749 //
       
   750 // If a valid drive is specified then the query is only executed only on
       
   751 // that drive. If KDbManagerAllDrives is specified then the query is executed
       
   752 // separately on each available drive.
       
   753 // ----------------------------------------------------------------------------
       
   754 //
       
   755 EXPORT_C void CMPXDbManager::ExecuteQueryL(
       
   756     TInt aDrive,
       
   757     TRefByValue<const TDesC> aFmt,
       
   758     ...)
       
   759     {
       
   760     MPX_FUNC("CMPXDatabase::ExecuteQueryL");
       
   761 
       
   762     // make sure there is enough space on all drives affected
       
   763     CheckDiskSpaceL(aDrive);
       
   764 
       
   765     VA_LIST list;
       
   766     VA_START(list, aFmt);
       
   767 
       
   768     HBufC* selectBuf = FormatQueryLC(aFmt, list);
       
   769     TPtr selectBufPtr = selectBuf->Des();
       
   770     TInt dbCount(iDatabaseHandles.Count());
       
   771 
       
   772     // a specified drive or all drives
       
   773     TInt loopCount = (aDrive == KDbManagerAllDrives) ? (dbCount + 1) : 1;
       
   774     TBool queryExecuted(EFalse); // flag to check if the query was executed at least once
       
   775     for (TInt j = 0; j < loopCount; ++j)
       
   776         {
       
   777         HBufC* query = HBufC::NewLC(selectBufPtr.Length() + KBufIncrement);
       
   778         TPtr queryPtr = query->Des();
       
   779         queryPtr.Copy(selectBufPtr);
       
   780         if (aDrive == EDriveC) // if C drive only
       
   781             {
       
   782             RemoveDriveAlias(queryPtr);
       
   783             }
       
   784         else // all drives or a particular drive other than C drive
       
   785             {
       
   786             if (aDrive == 0) // all drives
       
   787                 {
       
   788                 if (j == dbCount) // C drive
       
   789                     {
       
   790                     RemoveDriveAlias(queryPtr);
       
   791                     }
       
   792                 else //all other drives, except C drive
       
   793                     {
       
   794                     if (iDatabaseHandles[j].iOpen)
       
   795                         {
       
   796                         ReplaceDriveAlias(queryPtr, *(iDatabaseHandles[j].iAliasname));
       
   797                         }
       
   798                     }
       
   799                 }
       
   800             else //a particular drive, other than C drive
       
   801                 {
       
   802                 for (TInt i = 0; i < dbCount; ++i)
       
   803                     {
       
   804                     if (iDatabaseHandles[i].iOpen && iDatabaseHandles[i].iDrive == aDrive)
       
   805                         {
       
   806                         ReplaceDriveAlias(queryPtr, *(iDatabaseHandles[i].iAliasname));
       
   807                         break;
       
   808                         }
       
   809                     }
       
   810                 }
       
   811             }
       
   812         TInt dbnamePos = queryPtr.Find(KDBNameToken);// check if the query was created correctly
       
   813         if (dbnamePos == KErrNotFound)
       
   814             {
       
   815             // log the query
       
   816             TPtrC ptr(query->Left(KMaxLogQuery));
       
   817             MPX_DEBUG2("Query: %S", &ptr);
       
   818 
       
   819             User::LeaveIfError(ExecuteSqlStatement(iDatabase, queryPtr));
       
   820             queryExecuted = ETrue;
       
   821             }
       
   822         CleanupStack::PopAndDestroy(query);
       
   823         }   //for (TInt j = 0; j < loopCount; ++j)
       
   824     CleanupStack::PopAndDestroy(selectBuf);
       
   825     VA_END(list);
       
   826     if (!queryExecuted && aDrive !=   0)
       
   827         {
       
   828         // the requested drive(s) is not open
       
   829         User::Leave(KErrNotFound);
       
   830         }
       
   831     }
       
   832 
       
   833 // ----------------------------------------------------------------------------
       
   834 // CMPXDbManager::FormatQueryLC
       
   835 // ----------------------------------------------------------------------------
       
   836 //
       
   837 HBufC* CMPXDbManager::FormatQueryLC(
       
   838     TRefByValue<const TDesC> aFmt,
       
   839     VA_LIST aList)
       
   840     {
       
   841     MPX_FUNC("CMPXDatabase::FormatQueryLC");
       
   842 
       
   843     TOverflowHandle overflow;
       
   844 
       
   845     HBufC* selectBuf = HBufC::NewLC(TDesC(aFmt).Length());//will reallocate
       
   846     selectBuf->Des().AppendFormatList(aFmt, aList, &overflow);
       
   847     while (overflow.GetOverflowFlag())
       
   848         {
       
   849         TInt len = selectBuf->Des().MaxLength() + KBufIncrement;
       
   850         CleanupStack::PopAndDestroy(selectBuf);
       
   851         selectBuf = HBufC::NewLC(len);
       
   852         selectBuf->Des().AppendFormatList(aFmt, aList, &overflow);
       
   853         }
       
   854 
       
   855     return selectBuf;
       
   856     }
       
   857 
       
   858 // ----------------------------------------------------------------------------
       
   859 // Executes a select query against a specified drive
       
   860 // ----------------------------------------------------------------------------
       
   861 //
       
   862 EXPORT_C RSqlStatement CMPXDbManager::ExecuteSelectQueryOnAllDrivesL(
       
   863     TInt aDrive,
       
   864     TRefByValue<const TDesC> aFmt,
       
   865     ...)
       
   866     {
       
   867     MPX_FUNC("CMPXDatabase::ExecuteSelectQueryL");
       
   868 
       
   869     VA_LIST list;
       
   870     VA_START(list, aFmt);
       
   871 
       
   872     // Will reallocate
       
   873     HBufC* selectBuf = FormatQueryLC(aFmt, list);
       
   874     RSqlStatement statement = ExecuteSelectQueryOnAllDrivesL(aDrive, selectBuf->Des());
       
   875     CleanupStack::PopAndDestroy(selectBuf);
       
   876 
       
   877     VA_END(list);
       
   878 
       
   879     return statement;
       
   880     }
       
   881 
       
   882 // ----------------------------------------------------------------------------
       
   883 // CMPXDbManager::ExecuteSelectQueryOnAllDrivesL
       
   884 // ----------------------------------------------------------------------------
       
   885 //
       
   886 RSqlStatement CMPXDbManager::ExecuteSelectQueryOnAllDrivesL(
       
   887     TPtr aQuery)
       
   888     {
       
   889     MPX_FUNC("CMPXDatabase::ExecuteSelectQueryOnAllDrivesL");
       
   890 
       
   891     TInt dbCount = iDatabaseHandles.Count();
       
   892     HBufC* query = HBufC::NewLC(aQuery.Length() * (dbCount + 1) +
       
   893         KUnionAllToken().Length() * dbCount);
       
   894     TPtr queryPtr = query->Des();
       
   895     HBufC* selectOutBuf = NULL;
       
   896     TInt enclosed = aQuery.Mid(1, aQuery.Length() - 1).Find(KSelectToken);
       
   897     if (enclosed != KErrNotFound)
       
   898         {
       
   899         enclosed++;//to compensate the indent
       
   900         selectOutBuf = HBufC::NewLC(aQuery.Length() * (dbCount + 1) +
       
   901             KUnionAllToken().Length() * dbCount);
       
   902         selectOutBuf->Des().Copy(aQuery.Left(enclosed));
       
   903         selectOutBuf->Des().Append(aQuery.Right(1));//the closing bracket
       
   904         aQuery.Delete(0, enclosed);
       
   905         aQuery.Delete(aQuery.Length() - 1, 1);
       
   906         }
       
   907 
       
   908     HBufC* orderBuf = NULL;
       
   909     TInt orderPos = aQuery.Find(KOrderByToken);
       
   910     if (orderPos != KErrNotFound)
       
   911         {
       
   912         orderBuf = aQuery.Right(aQuery.Length() - orderPos).AllocL();
       
   913         aQuery.Delete(orderPos, aQuery.Length() - orderPos);
       
   914         }
       
   915     queryPtr.Append(aQuery);// for cdrive
       
   916     RemoveDriveAlias(queryPtr);
       
   917     for (TInt i = 0; i < dbCount; ++i)//for other drives
       
   918         {
       
   919         if (iDatabaseHandles[i].iOpen)
       
   920             {
       
   921             queryPtr.Append(KUnionAllToken);
       
   922             queryPtr.Append(aQuery);
       
   923             ReplaceDriveAlias(queryPtr, *(iDatabaseHandles[i].iAliasname));
       
   924             }
       
   925         }
       
   926     if (orderBuf)
       
   927         {
       
   928         queryPtr.Append(orderBuf->Des());
       
   929         }
       
   930     delete orderBuf;
       
   931     if (enclosed != KErrNotFound)
       
   932         {
       
   933         selectOutBuf->Des().Insert(enclosed, query->Des());
       
   934         queryPtr.Copy(selectOutBuf->Des());
       
   935         CleanupStack::PopAndDestroy(selectOutBuf);
       
   936         }
       
   937 
       
   938     // Log the query string before execution
       
   939     TPtrC ptr(query->Left(KMaxLogQuery));
       
   940     MPX_DEBUG2("Query: %S", &ptr);
       
   941 
       
   942     // Return a temporary statement and not a member variable.
       
   943     // This ensures that a copy is done and a second embedded query can be
       
   944     // executed while the first result set is processed.
       
   945     RSqlStatement statement;
       
   946     User::LeaveIfError(statement.Prepare(iDatabase, queryPtr));
       
   947     CleanupStack::PopAndDestroy(query);
       
   948 
       
   949     return statement;
       
   950     }
       
   951 
       
   952 // ----------------------------------------------------------------------------
       
   953 // CMPXDbManager::ExecuteSelectQueryOnAllDrivesL
       
   954 // ----------------------------------------------------------------------------
       
   955 //
       
   956 RSqlStatement CMPXDbManager::ExecuteSelectQueryOnAllDrivesL( TInt aDrive,
       
   957     TPtr aQuery)
       
   958     {
       
   959     MPX_FUNC("CMPXDatabase::ExecuteSelectQueryOnAllDrivesL");
       
   960 
       
   961     TInt dbCount = iDatabaseHandles.Count();
       
   962     HBufC* query = HBufC::NewLC(aQuery.Length() * (dbCount + 1) +
       
   963         KUnionAllToken().Length() * dbCount);
       
   964     TPtr queryPtr = query->Des();
       
   965     HBufC* selectOutBuf = NULL;
       
   966     TInt enclosed = aQuery.Mid(1, aQuery.Length() - 1).Find(KSelectToken);
       
   967     if (enclosed != KErrNotFound)
       
   968         {
       
   969         enclosed++;//to compensate the indent
       
   970         selectOutBuf = HBufC::NewLC(aQuery.Length() * (dbCount + 1) +
       
   971             KUnionAllToken().Length() * dbCount);
       
   972         selectOutBuf->Des().Copy(aQuery.Left(enclosed));
       
   973         selectOutBuf->Des().Append(aQuery.Right(1));//the closing bracket
       
   974         aQuery.Delete(0, enclosed);
       
   975         aQuery.Delete(aQuery.Length() - 1, 1);
       
   976         }
       
   977 
       
   978     HBufC* orderBuf = NULL;
       
   979     TInt orderPos = aQuery.Find(KOrderByToken);
       
   980     if (orderPos != KErrNotFound)
       
   981         {
       
   982         orderBuf = aQuery.Right(aQuery.Length() - orderPos).AllocL();
       
   983         aQuery.Delete(orderPos, aQuery.Length() - orderPos);
       
   984         }
       
   985     
       
   986     //remove KPlDBNameToken
       
   987     if ( aDrive == EDriveC )//if playlist on c drive
       
   988     	{
       
   989     	RemoveDriveAlias(aQuery,KPlDBNameToken);
       
   990     	}
       
   991     else
       
   992     	{//for other drives
       
   993 	    for (TInt i = 0; i < dbCount; ++i)
       
   994 	        {
       
   995 	        if (iDatabaseHandles[i].iOpen && (iDatabaseHandles[i].iDrive == aDrive))
       
   996 	            {
       
   997 	            ReplaceDriveAlias(aQuery, *(iDatabaseHandles[i].iAliasname),
       
   998 	            		KPlDBNameToken);
       
   999 	            break;
       
  1000 	            }
       
  1001 	        }
       
  1002     	}
       
  1003     
       
  1004     queryPtr.Append(aQuery);// for cdrive
       
  1005     RemoveDriveAlias(queryPtr);
       
  1006     for (TInt i = 0; i < dbCount; ++i)//for other drives
       
  1007         {
       
  1008         if (iDatabaseHandles[i].iOpen)
       
  1009             {
       
  1010             queryPtr.Append(KUnionAllToken);
       
  1011             queryPtr.Append(aQuery);
       
  1012             ReplaceDriveAlias(queryPtr, *(iDatabaseHandles[i].iAliasname));
       
  1013             }
       
  1014         }
       
  1015    
       
  1016     if (orderBuf)
       
  1017         {
       
  1018         queryPtr.Append(orderBuf->Des());
       
  1019         }
       
  1020     delete orderBuf;
       
  1021     if (enclosed != KErrNotFound)
       
  1022         {
       
  1023         selectOutBuf->Des().Insert(enclosed, query->Des());
       
  1024         queryPtr.Copy(selectOutBuf->Des());
       
  1025         CleanupStack::PopAndDestroy(selectOutBuf);
       
  1026         }
       
  1027 
       
  1028     // Log the query string before execution
       
  1029     TPtrC ptr(query->Left(KMaxLogQuery));
       
  1030     MPX_DEBUG2("Query: %S", &ptr);
       
  1031 
       
  1032     // Return a temporary statement and not a member variable.
       
  1033     // This ensures that a copy is done and a second embedded query can be
       
  1034     // executed while the first result set is processed.
       
  1035     RSqlStatement statement;
       
  1036     TInt err(statement.Prepare(iDatabase, queryPtr));
       
  1037     User::LeaveIfError(err);
       
  1038     CleanupStack::PopAndDestroy(query);
       
  1039 
       
  1040     return statement;
       
  1041     }
       
  1042 
       
  1043 // ----------------------------------------------------------------------------
       
  1044 // CMPXDbManager::ExecuteSelectQueryOnDriveLryLC
       
  1045 // ----------------------------------------------------------------------------
       
  1046 //
       
  1047 RSqlStatement CMPXDbManager::ExecuteSelectQueryOnDriveL(
       
  1048     TInt aDrive,
       
  1049     TPtr aQuery)
       
  1050     {
       
  1051     MPX_FUNC("CMPXDatabase::ExecuteSelectQueryOnDriveL");
       
  1052 
       
  1053     RSqlStatement statement;
       
  1054     if (KDbManagerAllDrives == aDrive)
       
  1055         {
       
  1056         statement = ExecuteSelectQueryOnAllDrivesL(aQuery);
       
  1057         }
       
  1058     else
       
  1059         {
       
  1060         TInt dbCount(iDatabaseHandles.Count());
       
  1061 
       
  1062         // flag to check if the query was executed at least once
       
  1063         TBool queryExecuted = EFalse;
       
  1064 
       
  1065         HBufC* query = HBufC::NewLC(aQuery.Length() + KBufIncrement);
       
  1066         TPtr queryPtr = query->Des();
       
  1067         queryPtr.Copy(aQuery);
       
  1068         if (aDrive == EDriveC) //if C drive
       
  1069             {
       
  1070             RemoveDriveAlias(queryPtr);
       
  1071             }
       
  1072         else // drive other than C drive
       
  1073             {
       
  1074             for (TInt i = 0; i < dbCount; ++i)
       
  1075                 {
       
  1076                 if (iDatabaseHandles[i].iOpen && (iDatabaseHandles[i].iDrive == aDrive))
       
  1077                     {
       
  1078                     ReplaceDriveAlias(queryPtr, *(iDatabaseHandles[i].iAliasname));
       
  1079                     break;
       
  1080                     }
       
  1081                 }
       
  1082             }
       
  1083 
       
  1084         TInt dbnamePos = queryPtr.Find(KDBNameToken);// check if the query was created correctly
       
  1085         if (dbnamePos == KErrNotFound)
       
  1086             {
       
  1087             // Log the query string before execution
       
  1088             TPtrC ptr(query->Left(KMaxLogQuery));
       
  1089             MPX_DEBUG2("Query: %S", &ptr);
       
  1090 
       
  1091             User::LeaveIfError(statement.Prepare(iDatabase, queryPtr));
       
  1092             queryExecuted = ETrue;
       
  1093             }
       
  1094         CleanupStack::PopAndDestroy(query);
       
  1095 
       
  1096         if (!queryExecuted)
       
  1097             {
       
  1098             // the requested drive(s) is not open
       
  1099             User::Leave(KErrNotFound);
       
  1100             }
       
  1101         }
       
  1102 
       
  1103     return statement;
       
  1104     }
       
  1105 
       
  1106 // ----------------------------------------------------------------------------
       
  1107 // Prepare a query for execution on all open database. This query's lifetime
       
  1108 // is owned by the dbmanager
       
  1109 // ----------------------------------------------------------------------------
       
  1110 //
       
  1111 RSqlStatement& CMPXDbManager::PrepareQueryL( TUint aStatementId,
       
  1112                                              TRefByValue<const TDesC> aFmt,
       
  1113                                              VA_LIST aList )
       
  1114     {
       
  1115     // Try to find the query first if it has been created
       
  1116     TInt index(KErrNotFound);
       
  1117     TInt c(iPreparedStatements.Count());
       
  1118 
       
  1119     for( TInt i=0; i<c; ++i )
       
  1120         {
       
  1121         if( iPreparedStatements[i].iId == aStatementId )
       
  1122             {
       
  1123             index = i;
       
  1124             break;
       
  1125             }
       
  1126         }
       
  1127 
       
  1128     // If the index isn't found we create a new query statement
       
  1129     //
       
  1130     if( index == KErrNotFound )
       
  1131         {
       
  1132         RSqlStatement* newStatement = new(ELeave) RSqlStatement();
       
  1133         CleanupStack::PushL(newStatement);
       
  1134 
       
  1135         TSqlStatementState newState;
       
  1136         newState.iId = aStatementId;
       
  1137         newState.iPrepared = EFalse;
       
  1138         iPreparedStatements.AppendL( newState );
       
  1139 
       
  1140         TInt err = iStatements.Append( newStatement ); // ownership x-fer
       
  1141         if (err != KErrNone)
       
  1142             {
       
  1143             iPreparedStatements.Remove(c);
       
  1144             User::Leave(err);
       
  1145             }
       
  1146         CleanupStack::Pop(newStatement);
       
  1147         index = c;
       
  1148         }
       
  1149 
       
  1150     // Finally create the statement
       
  1151     if ( !iPreparedStatements[index].iPrepared )
       
  1152         {
       
  1153 
       
  1154         // Will reallocate
       
  1155         HBufC* selectBuf = FormatQueryLC(aFmt, aList);
       
  1156         TPtr selectBufPtr = selectBuf->Des();
       
  1157         TInt dbCount = iDatabaseHandles.Count();
       
  1158         HBufC* query = HBufC::NewLC(selectBufPtr.Length() * (dbCount + 1) +
       
  1159             KUnionAllToken().Length() * dbCount);
       
  1160         TPtr queryPtr = query->Des();
       
  1161         HBufC* selectOutBuf = NULL;
       
  1162         TInt enclosed = selectBufPtr.Mid(1,selectBufPtr.Length() - 1).Find(KSelectToken);
       
  1163         if (enclosed != KErrNotFound)
       
  1164             {
       
  1165             enclosed++;//to compensate the indent
       
  1166             selectOutBuf = HBufC::NewLC(selectBufPtr.Length() * (dbCount + 1) +
       
  1167                 KUnionAllToken().Length() * dbCount);
       
  1168             selectOutBuf->Des().Copy(selectBufPtr.Left(enclosed));
       
  1169             selectOutBuf->Des().Append(selectBufPtr.Right(1));//the closing bracket
       
  1170             selectBufPtr.Delete(0, enclosed);
       
  1171             selectBufPtr.Delete(selectBufPtr.Length()   -   1, 1);
       
  1172             }
       
  1173 
       
  1174         HBufC* orderBuf = NULL;
       
  1175         TInt orderPos = selectBufPtr.Find(KOrderByToken);
       
  1176         if (orderPos != KErrNotFound)
       
  1177             {
       
  1178             orderBuf = selectBufPtr.Right(selectBufPtr.Length() - orderPos).AllocL();
       
  1179             selectBufPtr.Delete(orderPos,   selectBufPtr.Length() - orderPos);
       
  1180             }
       
  1181         queryPtr.Append(selectBufPtr);// for cdrive
       
  1182         RemoveDriveAlias(queryPtr);
       
  1183         for (TInt i = 0; i < dbCount; ++i)//for other drives
       
  1184             {
       
  1185             if (iDatabaseHandles[i].iOpen)
       
  1186                 {
       
  1187                 queryPtr.Append(KUnionAllToken);
       
  1188                 queryPtr.Append(selectBufPtr);
       
  1189                 ReplaceDriveAlias(queryPtr, *(iDatabaseHandles[i].iAliasname));
       
  1190                 }
       
  1191             }
       
  1192         if (orderBuf)
       
  1193             {
       
  1194             queryPtr.Append(orderBuf->Des());
       
  1195             }
       
  1196         delete orderBuf;
       
  1197         if (enclosed != KErrNotFound)
       
  1198             {
       
  1199             selectOutBuf->Des().Insert(enclosed, query->Des());
       
  1200             queryPtr.Copy(selectOutBuf->Des());
       
  1201             CleanupStack::PopAndDestroy(selectOutBuf);
       
  1202             }
       
  1203 
       
  1204         // Log the query string before execution
       
  1205         TPtrC ptr(query->Left(KMaxLogQuery));
       
  1206         MPX_DEBUG2("Query: %S", &ptr);
       
  1207 
       
  1208         // use the member variable statement
       
  1209         User::LeaveIfError(iStatements[index]->Prepare(iDatabase, queryPtr));
       
  1210         CleanupStack::PopAndDestroy(2, selectBuf); //query
       
  1211 
       
  1212         iPreparedStatements[index].iPrepared = ETrue;
       
  1213         }
       
  1214     else
       
  1215         {
       
  1216         iStatements[index]->Reset();
       
  1217         }
       
  1218 
       
  1219     return *iStatements[index];
       
  1220     }
       
  1221 
       
  1222 // ----------------------------------------------------------------------------
       
  1223 // Resets all prepared queries
       
  1224 // ----------------------------------------------------------------------------
       
  1225 //
       
  1226 void CMPXDbManager::ResetPreparedQueries()
       
  1227     {
       
  1228     iPreparedStatements.Reset();
       
  1229 
       
  1230     TInt c( iStatements.Count() );
       
  1231     for( TInt i=0; i<c; ++i )
       
  1232         {
       
  1233         iStatements[i]->Close();
       
  1234         }
       
  1235     iStatements.ResetAndDestroy();
       
  1236     }
       
  1237 
       
  1238 // ----------------------------------------------------------------------------
       
  1239 // Asks all registered tables to create themselves
       
  1240 // ----------------------------------------------------------------------------
       
  1241 //
       
  1242 EXPORT_C void CMPXDbManager::CreateTablesL(
       
  1243     RSqlDatabase& aDatabase)
       
  1244     {
       
  1245     MPX_FUNC("CMPXDbManager::CreateTablesL");
       
  1246 
       
  1247 	CreateTablesL(aDatabase, EFalse);
       
  1248     }
       
  1249 
       
  1250 // ----------------------------------------------------------------------------
       
  1251 // CMPXDbManager::CreateTablesL
       
  1252 // ----------------------------------------------------------------------------
       
  1253 //
       
  1254 void CMPXDbManager::CreateTablesL(
       
  1255 	RSqlDatabase& aDatabase,
       
  1256 	TBool aCorrupt)
       
  1257 	{
       
  1258     TInt count(iTables.Count());
       
  1259     for (TInt i = 0; i < count; ++i)
       
  1260         {
       
  1261         iTables[i]->CreateTableL(aDatabase, aCorrupt);
       
  1262         }
       
  1263 	}
       
  1264 
       
  1265 // ----------------------------------------------------------------------------
       
  1266 // Opens a specified database.
       
  1267 // ----------------------------------------------------------------------------
       
  1268 //
       
  1269 void CMPXDbManager::OpenDatabaseL(
       
  1270     TDriveUnit aDrive)
       
  1271     {
       
  1272     MPX_FUNC("CMPXDbManager::OpenDatabaseL");
       
  1273 
       
  1274     HBufC * filename = CreateFilenameL(aDrive);
       
  1275     CleanupStack::PushL(filename);
       
  1276     User::LeaveIfError(iDatabase.Open(filename->Des()));
       
  1277 
       
  1278     CleanupStack::PopAndDestroy(filename);
       
  1279     }
       
  1280 
       
  1281 // ----------------------------------------------------------------------------
       
  1282 // Creates a specified database.
       
  1283 // ----------------------------------------------------------------------------
       
  1284 //
       
  1285 void CMPXDbManager::CreateDatabaseL(
       
  1286     TDriveUnit aDrive)
       
  1287     {
       
  1288     MPX_FUNC("CMPXDbManager::CreateDatabaseL");
       
  1289 
       
  1290     RSqlDatabase database;
       
  1291     CleanupClosePushL(database);
       
  1292 
       
  1293     HBufC* filename = CreateFilenameL(aDrive);
       
  1294     CleanupStack::PushL(filename);
       
  1295 
       
  1296     if (database.Open(filename->Des()) != KErrNone)
       
  1297         {
       
  1298         MPX_DEBUG2("CMPXDbManager::CreateDatabaseL - cannot open the database on drive %d", TInt(aDrive));
       
  1299 
       
  1300         // close the database first
       
  1301         database.Close();
       
  1302         DoCreateDatabaseL( aDrive );
       
  1303         }
       
  1304     else
       
  1305         {
       
  1306         TBool tableOK(ETrue);
       
  1307 
       
  1308         // try to detect any corrupt tables
       
  1309         TInt count(iTables.Count());
       
  1310         for (TInt i = 0; i < count; ++i)
       
  1311             {
       
  1312             // ask the table to check its structure
       
  1313             if (!iTables[i]->CheckTableL(database))
       
  1314                 {
       
  1315                 tableOK = EFalse;
       
  1316                 break;
       
  1317                 }
       
  1318             }
       
  1319 
       
  1320         if (!tableOK)
       
  1321             {
       
  1322             // close the database first
       
  1323             database.Close();
       
  1324 			
       
  1325 			// delete database and create database
       
  1326             DoCreateDatabaseL( aDrive );
       
  1327             }
       
  1328         }
       
  1329     CleanupStack::PopAndDestroy(filename);
       
  1330     CleanupStack::PopAndDestroy(&database);
       
  1331     }
       
  1332 
       
  1333 // ----------------------------------------------------------------------------
       
  1334 // Attaches a specified database.
       
  1335 // ----------------------------------------------------------------------------
       
  1336 //
       
  1337 void CMPXDbManager::AttachDatabaseL(
       
  1338     TDriveUnit aDrive)
       
  1339     {
       
  1340     MPX_FUNC("CMPXDbManager::AttachDatabaseL");
       
  1341 
       
  1342     TBool found(EFalse);
       
  1343 
       
  1344     TInt count(iDatabaseHandles.Count());
       
  1345     for (TInt i = 0; i < count; ++i)
       
  1346         {
       
  1347         if (iDatabaseHandles[i].iDrive == aDrive)
       
  1348             {
       
  1349             if (!iDatabaseHandles[i].iOpen)
       
  1350                 {
       
  1351                 HBufC* filename = CreateFilenameL(aDrive);
       
  1352                 CleanupStack::PushL(filename);
       
  1353 
       
  1354                 User::LeaveIfError(iDatabase.Attach(filename->Des(),
       
  1355                     *(iDatabaseHandles[i].iAliasname)));
       
  1356                 iDatabaseHandles[i].iOpen = ETrue;
       
  1357 
       
  1358                 CleanupStack::PopAndDestroy(filename);
       
  1359                 }
       
  1360             found = ETrue;
       
  1361             break;
       
  1362             }
       
  1363         }
       
  1364     if (!found)
       
  1365         {
       
  1366         User::Leave(KErrNotFound);
       
  1367         }
       
  1368     }
       
  1369 
       
  1370 // ----------------------------------------------------------------------------
       
  1371 // Detaches a specified database.
       
  1372 // ----------------------------------------------------------------------------
       
  1373 //
       
  1374 void CMPXDbManager::DetachDatabaseL(
       
  1375     TDriveUnit aDrive)
       
  1376     {
       
  1377     MPX_FUNC("CMPXDbManager::DetachDatabaseL");
       
  1378 
       
  1379     ASSERT(iInitialized);
       
  1380     TBool found(EFalse);
       
  1381 
       
  1382     TInt count(iDatabaseHandles.Count());
       
  1383     for (TInt i = 0; i < count; ++i)
       
  1384         {
       
  1385         if (iDatabaseHandles[i].iDrive == aDrive)
       
  1386             {
       
  1387             if (iDatabaseHandles[i].iOpen)
       
  1388                 {
       
  1389                 User::LeaveIfError(iDatabase.Detach(*(iDatabaseHandles[i].iAliasname)));
       
  1390                 iDatabaseHandles[i].iOpen = EFalse;
       
  1391                 }
       
  1392 
       
  1393             found = ETrue;
       
  1394             break;
       
  1395             }
       
  1396         }
       
  1397     if (!found)
       
  1398         {
       
  1399         User::Leave(KErrNotFound);
       
  1400         }
       
  1401     }
       
  1402 
       
  1403 // ----------------------------------------------------------------------------
       
  1404 // Creates the absolute database filename on a specified drive.
       
  1405 // ----------------------------------------------------------------------------
       
  1406 //
       
  1407 HBufC* CMPXDbManager::CreateFilenameL(
       
  1408     TDriveUnit aDrive)
       
  1409     {
       
  1410     MPX_FUNC("CMPXDbManager::CreateFilenameL");
       
  1411 
       
  1412     HBufC* filename = HBufC::NewL(KMaxFileName);
       
  1413 
       
  1414     const TDesC& securefilePath = KSecureFilePath;
       
  1415     TDriveUnit cdrive(KRootDrive());
       
  1416 
       
  1417     const TDesC& driveName = aDrive.Name();
       
  1418     filename->Des().Format(securefilePath, &driveName, User::Identity().iUid, iDbFile);
       
  1419     return filename;
       
  1420     }
       
  1421 
       
  1422 // ----------------------------------------------------------------------------
       
  1423 // Replaces :dbname with a drive alias
       
  1424 // ----------------------------------------------------------------------------
       
  1425 //
       
  1426 void CMPXDbManager::ReplaceDriveAlias(
       
  1427     TDes& aQuery,
       
  1428     const TDesC& aAlias)
       
  1429     {
       
  1430 //  MPX_FUNC("CMPXDbManager::ReplaceDriveAlias");
       
  1431 
       
  1432     TInt dbnamePos(aQuery.Find(KDBNameToken));
       
  1433     while (dbnamePos != KErrNotFound)
       
  1434         {
       
  1435         aQuery.Delete(dbnamePos, KDBNameToken().Length());
       
  1436         aQuery.Insert(dbnamePos, aAlias);
       
  1437         dbnamePos = aQuery.Find(KDBNameToken);
       
  1438         }
       
  1439     }
       
  1440 
       
  1441 // ----------------------------------------------------------------------------
       
  1442 // Replaces :dbname with a drive alias
       
  1443 // ----------------------------------------------------------------------------
       
  1444 //
       
  1445 void CMPXDbManager::ReplaceDriveAlias(
       
  1446     TDes& aQuery,
       
  1447     const TDesC& aAlias,
       
  1448     const TDesC& aToKen)
       
  1449     {
       
  1450     
       
  1451     TInt dbnamePos(aQuery.Find(aToKen));
       
  1452     while (dbnamePos != KErrNotFound)
       
  1453         {
       
  1454         aQuery.Delete(dbnamePos, aToKen.Length());
       
  1455         aQuery.Insert(dbnamePos, aAlias);
       
  1456         dbnamePos = aQuery.Find(aToKen);
       
  1457         }
       
  1458     }
       
  1459 
       
  1460 // ----------------------------------------------------------------------------
       
  1461 // Removes :dbname
       
  1462 // ----------------------------------------------------------------------------
       
  1463 //
       
  1464 void CMPXDbManager::RemoveDriveAlias(
       
  1465     TDes& aQuery)
       
  1466     {
       
  1467     MPX_FUNC("CMPXDbManager::RemoveDriveAlias");
       
  1468 
       
  1469     TInt dbnamePos(aQuery.Find(KDBNameToken));
       
  1470     while (dbnamePos != KErrNotFound)
       
  1471         {
       
  1472         aQuery.Delete(dbnamePos, KDBNameToken().Length() + 1);
       
  1473         dbnamePos = aQuery.Find(KDBNameToken);
       
  1474         }
       
  1475     }
       
  1476 
       
  1477 
       
  1478 // ----------------------------------------------------------------------------
       
  1479 // Removes :dbname
       
  1480 // ----------------------------------------------------------------------------
       
  1481 //
       
  1482 void CMPXDbManager::RemoveDriveAlias(
       
  1483     TDes& aQuery,const TDesC& aToKen)
       
  1484     {
       
  1485     MPX_FUNC("CMPXDbManager::RemoveDriveAlias");
       
  1486 
       
  1487     TInt dbnamePos(aQuery.Find(aToKen));
       
  1488     while (dbnamePos != KErrNotFound)
       
  1489         {
       
  1490         aQuery.Delete(dbnamePos, aToKen.Length() + 1);
       
  1491         dbnamePos = aQuery.Find(aToKen);
       
  1492         }
       
  1493     }
       
  1494 
       
  1495 
       
  1496 // ----------------------------------------------------------------------------
       
  1497 // CMPXDbManager::CheckDiskSpaceL
       
  1498 // ----------------------------------------------------------------------------
       
  1499 //
       
  1500 EXPORT_C void CMPXDbManager::CheckDiskSpaceL(
       
  1501     TInt aDrive)
       
  1502     {
       
  1503     MPX_FUNC("CMPXDbManager::CheckDiskSpaceL");
       
  1504     
       
  1505     // LTAN-7GH6BZ, crash if eject memory card when adding song to existing playlist
       
  1506     // due to special timing issue, it is possible drive number is -1 and create a
       
  1507     // panic when use for TDriveUnit
       
  1508     MPX_DEBUG2("aDrive = %d", aDrive);
       
  1509     
       
  1510     if (aDrive < 0)
       
  1511         {
       
  1512         MPX_DEBUG1("invalid driveId, leave with KErrNotReady");
       
  1513         User::Leave(KErrNotReady);
       
  1514         }
       
  1515 
       
  1516     // handle the case of C drive
       
  1517     TDriveUnit drive(aDrive);
       
  1518     TDriveUnit cdrive(KRootDrive());
       
  1519 
       
  1520     if(drive == cdrive)
       
  1521         {
       
  1522         if (SysUtil::DiskSpaceBelowCriticalLevelL(&iFs, 0, aDrive))
       
  1523             {
       
  1524             User::Leave(KErrDiskFull);
       
  1525             }
       
  1526 
       
  1527         return;
       
  1528         }
       
  1529 
       
  1530     // handle other drives (eg. removable EDriveE)
       
  1531     TInt count(iDatabaseHandles.Count());
       
  1532     for (TInt i = 0; i < count; ++i)
       
  1533         {
       
  1534 
       
  1535         if (((KDbManagerAllDrives == aDrive) ||
       
  1536             (aDrive == iDatabaseHandles[i].iDrive)) &&
       
  1537             iDatabaseHandles[i].iOpen)
       
  1538             {
       
  1539             if (SysUtil::DiskSpaceBelowCriticalLevelL(&iFs, 0,
       
  1540                 iDatabaseHandles[i].iDrive))
       
  1541                 {
       
  1542                 User::Leave(KErrDiskFull);
       
  1543                 }
       
  1544             }
       
  1545 
       
  1546         if (aDrive == iDatabaseHandles[i].iDrive)
       
  1547             {
       
  1548             // exit if just one drive to check
       
  1549             break;
       
  1550             }
       
  1551         }
       
  1552     }
       
  1553     
       
  1554 // ----------------------------------------------------------------------------
       
  1555 // Regenerate all databases.
       
  1556 // ----------------------------------------------------------------------------
       
  1557 //
       
  1558 EXPORT_C void CMPXDbManager::RegenerateAllDatabasesL()
       
  1559     {
       
  1560     MPX_DEBUG1("CMPXDbManager::RegenerateAllDatabasesL Enter");
       
  1561     ResetPreparedQueries(); //just in case ...
       
  1562     TInt handles(iDatabaseHandles.Count());
       
  1563     for (TInt i = 0; i < handles; ++i)
       
  1564         {
       
  1565         iDatabaseHandles[i].iOpen = EFalse; //attach will open them again
       
  1566         }    
       
  1567     iDatabase.Close(); //close the database before deleting the file
       
  1568     iInitialized = EFalse;
       
  1569 
       
  1570     MPX_DEBUG1("RegenerateAllDatabasesL: Regenerating main DB on C:");
       
  1571     HBufC * filename = CreateFilenameL(EDriveC);
       
  1572     CleanupStack::PushL(filename);
       
  1573     RSqlDatabase::Delete(*filename);
       
  1574     TDriveUnit cdrive(KRootDrive());
       
  1575     CreateDatabaseL(cdrive);
       
  1576     User::LeaveIfError(iDatabase.Open(*filename)); // will set handle status later
       
  1577     CleanupStack::PopAndDestroy(filename);
       
  1578     MPX_DEBUG1("RegenerateAllDatabasesL: DB regeneration complete");
       
  1579     
       
  1580     // Recreate all attached drives
       
  1581     TInt count(iDatabaseHandles.Count());
       
  1582     for (TInt i = 0; i < count; ++i)
       
  1583         {
       
  1584         if (iDatabaseHandles[i].iDrive != EDriveC)
       
  1585             {
       
  1586             MPX_DEBUG2("RegenerateAllDatabasesL: Regenerating DB on %d",iDatabaseHandles[i].iDrive);
       
  1587             TVolumeInfo volumeInfo; 
       
  1588             TInt err = iFs.Volume(volumeInfo,iDatabaseHandles[i].iDrive);
       
  1589             if(err != KErrNone)
       
  1590                 {
       
  1591                 continue; //if drive is not currently accessible, skip
       
  1592                 }
       
  1593             filename = CreateFilenameL(iDatabaseHandles[i].iDrive);
       
  1594             CleanupStack::PushL(filename);
       
  1595             MPX_DEBUG1("RegenerateAllDatabasesL: Detaching DB");
       
  1596             err = iDatabase.Detach(*(iDatabaseHandles[i].iAliasname)); //ignore the error if any
       
  1597             MPX_DEBUG2("RegenerateAllDatabasesL: Detached[err=%d]; Deleting DB",err);
       
  1598             err = RSqlDatabase::Delete(*filename);
       
  1599             MPX_DEBUG2("RegenerateAllDatabasesL: Deleted[err=%d]; Creating new DB",err);
       
  1600             TDriveUnit drive(iDatabaseHandles[i].iDrive);
       
  1601             CreateDatabaseL(drive);
       
  1602             MPX_DEBUG1("RegenerateAllDatabasesL: Attaching new DB");
       
  1603             AttachDatabaseL(drive);    
       
  1604             MPX_DEBUG1("RegenerateAllDatabasesL: DB regeneration complete");
       
  1605             CleanupStack::PopAndDestroy(filename);
       
  1606             }
       
  1607         else
       
  1608             {
       
  1609             iDatabaseHandles[i].iOpen = ETrue; //if we got here it is opened
       
  1610             }
       
  1611         }
       
  1612     iInitialized = ETrue;
       
  1613     MPX_DEBUG1("CMPXDbManager::RegenerateAllDatabasesL Exit");
       
  1614     }    
       
  1615 
       
  1616 // ----------------------------------------------------------------------------
       
  1617 // CMPXDbManager::DoRecreateDatabaseL
       
  1618 // ----------------------------------------------------------------------------
       
  1619 //
       
  1620 void CMPXDbManager::DoRecreateDatabaseL(HBufC * aFilename)
       
  1621     {
       
  1622     RSqlDatabase database;
       
  1623     CleanupClosePushL(database);
       
  1624 
       
  1625     User::LeaveIfError(database.Open(aFilename->Des()));
       
  1626 
       
  1627     TInt count(iTables.Count());
       
  1628     for (TInt i = 0; i < count; ++i)
       
  1629         {
       
  1630         iTables[i]->DropTableL(database);
       
  1631         iTables[i]->CreateTableL(database, EFalse);
       
  1632         }
       
  1633     CleanupStack::PopAndDestroy(&database);
       
  1634     }
       
  1635 
       
  1636 // ----------------------------------------------------------------------------
       
  1637 // CMPXDbManager::ExecuteSqlStatement
       
  1638 // ----------------------------------------------------------------------------
       
  1639 //
       
  1640 TInt CMPXDbManager::ExecuteSqlStatement(RSqlDatabase& aDatabase,const TDesC& aStatement)
       
  1641     {
       
  1642     MPX_FUNC("CMPXDbManager::ExecuteSqlStatement");
       
  1643     TInt result( KErrNone );
       
  1644     RSqlStatement sqlStatement;
       
  1645     //Prepare and execute SQL statement
       
  1646     result = sqlStatement.Prepare(aDatabase, aStatement);
       
  1647     if (result == KErrNone)
       
  1648         {
       
  1649         result = sqlStatement.Exec();
       
  1650         //If the database schema was changed or the session expired repeat all the steps
       
  1651         if((result == KSqlErrStmtExpired) || (result == KSqlErrSchema))
       
  1652             {
       
  1653             sqlStatement.Close();
       
  1654             result = sqlStatement.Prepare(aDatabase, aStatement);
       
  1655             if (result == KErrNone)
       
  1656                 {
       
  1657                 result = sqlStatement.Exec();
       
  1658                 }
       
  1659             }
       
  1660         sqlStatement.Close();
       
  1661         }
       
  1662     return result;
       
  1663     }
       
  1664 
       
  1665 #ifdef _DEBUG
       
  1666 
       
  1667 // ----------------------------------------------------------------------------
       
  1668 // Returns the number of columns from a specified SQL statement
       
  1669 // ----------------------------------------------------------------------------
       
  1670 //
       
  1671 TInt CMPXDbManager::GetColumnCountL(
       
  1672     RSqlStatement& aStatement)
       
  1673     {
       
  1674     TInt columnCount(0);
       
  1675 
       
  1676 // Using TSqlRowSetUtil causes linker errors on ARMv5 UDEB
       
  1677 // Enabling this functionality for WINSCW UDEB only
       
  1678 // PREQ2536 the files sqlrowsetutil.h and sqlrowsetutil.cpp has been removed
       
  1679 //#ifdef __WINSCW__
       
  1680 //
       
  1681 //    HBufC* headers = TSqlRowSetUtil::GetDeclColumnTypesL(aStatement);
       
  1682 //    CleanupStack::PushL(headers);
       
  1683 //
       
  1684 //    // Count the number of semicolons to get the number of columns
       
  1685 //    TPtr headerPtr = headers->Des();
       
  1686 //    TInt location(headerPtr.Locate(';'));
       
  1687 //    while ((location != KErrNotFound) && (location < headers->Length()))
       
  1688 //        {
       
  1689 //        ++columnCount;
       
  1690 //        if (++location < headers->Length())
       
  1691 //            {
       
  1692 //            headerPtr = headers->Des().Mid(location);
       
  1693 //            location = headerPtr.Locate(';');
       
  1694 //            }
       
  1695 //        }
       
  1696 //    CleanupStack::PopAndDestroy(headers);
       
  1697 //
       
  1698 //#else
       
  1699 	(void)aStatement;
       
  1700 //#endif
       
  1701 
       
  1702     return columnCount;
       
  1703     }
       
  1704 
       
  1705 // ----------------------------------------------------------------------------
       
  1706 // Prints the table values from a specified SQL query
       
  1707 // ----------------------------------------------------------------------------
       
  1708 //
       
  1709 void CMPXDbManager::PrintTableValuesL(
       
  1710     RSqlStatement& aStatement)
       
  1711     {
       
  1712     TInt columnCount(GetColumnCountL(aStatement));
       
  1713     TInt err(KErrNone);
       
  1714     HBufC* tableRow = HBufC::NewLC(255 * columnCount);
       
  1715     TPtr tableRowPtr = tableRow->Des();
       
  1716 
       
  1717     while ((err = aStatement.Next()) == KSqlAtRow)
       
  1718         {
       
  1719         tableRowPtr.Zero();
       
  1720         TInt error(KErrNone);
       
  1721         for (TInt index = 0; (error == KErrNone) && (index < columnCount); ++index)
       
  1722             {
       
  1723             if (index !=0)
       
  1724                 {
       
  1725                 tableRowPtr.Append(',');
       
  1726                 }
       
  1727             switch (aStatement.ColumnType(index))
       
  1728                 {
       
  1729                 case ESqlNull:
       
  1730                     tableRowPtr.Append(_L("<NULL>"));
       
  1731                     break;
       
  1732 
       
  1733                 case ESqlInt:
       
  1734                     {
       
  1735                     tableRowPtr.AppendFormat(_L("%u"), aStatement.ColumnInt(index));
       
  1736                     }
       
  1737                     break;
       
  1738 
       
  1739                 case ESqlInt64:
       
  1740                     {
       
  1741                     tableRowPtr.AppendFormat(_L("%lu"), aStatement.ColumnInt64(index));
       
  1742                     }
       
  1743                     break;
       
  1744 
       
  1745                 case ESqlReal:
       
  1746                     {
       
  1747                     tableRowPtr.AppendFormat(_L("%f"), aStatement.ColumnReal(index));
       
  1748                     }
       
  1749                     break;
       
  1750 
       
  1751                 case ESqlText:
       
  1752                     {
       
  1753                     TPtrC columnValue;
       
  1754                     error = aStatement.ColumnText(index, columnValue);
       
  1755                     if (error == KErrNone)
       
  1756                         {
       
  1757                         tableRowPtr.AppendFormat(_L("%S"), &columnValue);
       
  1758                         }
       
  1759                     }
       
  1760                     break;
       
  1761 
       
  1762                 case ESqlBinary:
       
  1763                     {
       
  1764                     TPtrC8 columnValue;
       
  1765                     error = aStatement.ColumnBinary(index, columnValue);
       
  1766                     if (error == KErrNone)
       
  1767                         {
       
  1768                         tableRowPtr.AppendFormat(_L("%S"), &columnValue);
       
  1769                         }
       
  1770                     }
       
  1771                     break;
       
  1772 
       
  1773                 default :
       
  1774                     ASSERT(EFalse);
       
  1775                 }
       
  1776 
       
  1777             if (tableRowPtr.Length() > 255)
       
  1778                 {
       
  1779                 tableRowPtr.SetLength(255);
       
  1780                 MPX_DEBUG2("%S", tableRow);
       
  1781                 tableRowPtr.Zero();
       
  1782                 }
       
  1783             }
       
  1784         if (tableRowPtr.Length() > 0)
       
  1785             {
       
  1786             tableRowPtr.SetLength(Min(tableRowPtr.Length(), 255));
       
  1787             MPX_DEBUG2("%S", tableRow);
       
  1788             }
       
  1789         }
       
  1790     CleanupStack::PopAndDestroy(tableRow);
       
  1791     if (err != KSqlAtEnd)
       
  1792         {
       
  1793         User::Leave(err);
       
  1794         }
       
  1795     }
       
  1796 
       
  1797 // ----------------------------------------------------------------------------
       
  1798 // Finds all the tables on the main or attached drives
       
  1799 // ----------------------------------------------------------------------------
       
  1800 //
       
  1801 void CMPXDbManager::FindAllTablesL(
       
  1802     const TDesC& aAlias,
       
  1803     RArray<HBufC*>& aTableName)
       
  1804     {
       
  1805     RSqlStatement statement;
       
  1806     CleanupClosePushL(statement);
       
  1807 
       
  1808     if (aAlias == KNullDesC)
       
  1809         {
       
  1810         statement.Prepare(iDatabase, KFindAllCDriveTablesQuery);
       
  1811         }
       
  1812     else
       
  1813         {
       
  1814         HBufC* query = KFindAllAttachedTablesQuery().AllocL();
       
  1815         CleanupStack::PushL(query);
       
  1816         TPtr queryPtr = query->Des();
       
  1817         ReplaceDriveAlias(queryPtr, aAlias);
       
  1818         statement.Prepare(iDatabase, queryPtr);
       
  1819         CleanupStack::PopAndDestroy(query);
       
  1820         }
       
  1821 
       
  1822     TInt err(KErrNone);
       
  1823 
       
  1824     while ((err = statement.Next()) == KSqlAtRow)
       
  1825         {
       
  1826         TPtrC val = statement.ColumnTextL(statement.ColumnIndex(KNameColumn));
       
  1827         aTableName.AppendL(val.AllocL());
       
  1828         }
       
  1829     if (err != KSqlAtEnd)
       
  1830         {
       
  1831         User::Leave(err);
       
  1832         }
       
  1833 
       
  1834     CleanupStack::PopAndDestroy(&statement);
       
  1835     }
       
  1836 
       
  1837 // ----------------------------------------------------------------------------
       
  1838 // Prints the tables on the main or attached drives
       
  1839 // ----------------------------------------------------------------------------
       
  1840 //
       
  1841 void CMPXDbManager::PrintTableL(
       
  1842     const TDesC& aAlias,
       
  1843     const TDesC& aTableName)
       
  1844     {
       
  1845     RSqlStatement statement;
       
  1846     CleanupClosePushL(statement);
       
  1847 
       
  1848     if (aAlias == KNullDesC)
       
  1849         {
       
  1850         HBufC* selectQuery = HBufC::NewLC(KTableQuery().Length() + aTableName.Length());
       
  1851         selectQuery->Des().Format(KTableQuery, &aTableName);
       
  1852         User::LeaveIfError(statement.Prepare(iDatabase, *selectQuery));
       
  1853         CleanupStack::PopAndDestroy(selectQuery);
       
  1854         }
       
  1855     else
       
  1856         {
       
  1857         HBufC* selectQuery = HBufC::NewLC(KAttachedTableQuery().Length() + aTableName.Length());
       
  1858         selectQuery->Des().Format(KAttachedTableQuery, &aTableName);
       
  1859 
       
  1860         TPtr selectQueryPtr(selectQuery->Des());
       
  1861         ReplaceDriveAlias(selectQueryPtr, aAlias);
       
  1862         User::LeaveIfError(statement.Prepare(iDatabase, *selectQuery));
       
  1863 
       
  1864         CleanupStack::PopAndDestroy(selectQuery);
       
  1865         }
       
  1866 
       
  1867     PrintTableValuesL(statement);
       
  1868     CleanupStack::PopAndDestroy(&statement);
       
  1869     }
       
  1870 
       
  1871 #endif
       
  1872 
       
  1873 // ----------------------------------------------------------------------------
       
  1874 // Prints all the tables on the main and attached drives
       
  1875 // ----------------------------------------------------------------------------
       
  1876 //
       
  1877 EXPORT_C void CMPXDbManager::PrintDatabaseL()
       
  1878     {
       
  1879 #ifdef _DEBUG
       
  1880     if (iInitialized)
       
  1881         {
       
  1882         // C-Drive
       
  1883         RArray<HBufC*> tableNames;
       
  1884         FindAllTablesL(KNullDesC(), tableNames);
       
  1885 
       
  1886         MPX_DEBUG1("### Drive C ###");
       
  1887 
       
  1888         TInt tableCount(tableNames.Count());
       
  1889         for (TInt i = 0; i < tableCount; ++i)
       
  1890             {
       
  1891             MPX_DEBUG2("# %S #", tableNames[i]);
       
  1892             MPX_TRAPD(error, PrintTableL(KNullDesC, *tableNames[i]));
       
  1893             delete tableNames[i];
       
  1894             if (error != KErrNone)
       
  1895                 {
       
  1896                 if (error != KErrPermissionDenied)
       
  1897                     {
       
  1898                     User::Leave(error);
       
  1899                     }
       
  1900                 else
       
  1901                     {
       
  1902                     MPX_DEBUG1("Unable to print table");
       
  1903                     }
       
  1904                 }
       
  1905             }
       
  1906         tableNames.Close();
       
  1907 
       
  1908         // Each attached drive
       
  1909         TInt count(iDatabaseHandles.Count());
       
  1910         for (TInt i = 0; i < count; ++i)
       
  1911             {
       
  1912             if (iDatabaseHandles[i].iOpen)
       
  1913                 {
       
  1914                 FindAllTablesL(iDatabaseHandles[i].iAliasname->Des(), tableNames);
       
  1915 
       
  1916                 TDriveUnit driveUnit(iDatabaseHandles[i].iDrive);
       
  1917                 const   TDesC& name = driveUnit.Name();
       
  1918                 MPX_DEBUG2("### Drive %S ###", &name);
       
  1919 
       
  1920                 for (TInt j = 0; j < tableCount; ++j)
       
  1921                     {
       
  1922                     MPX_DEBUG2("# %S #", tableNames[j]);
       
  1923                     MPX_TRAPD(error, PrintTableL(iDatabaseHandles[i].iAliasname->Des(), *tableNames[j]));
       
  1924                     delete tableNames[j];
       
  1925                     if (error != KErrNone)
       
  1926                         {
       
  1927                         if (error != KErrPermissionDenied)
       
  1928                             {
       
  1929                             User::Leave(error);
       
  1930                             }
       
  1931                         else
       
  1932                             {
       
  1933                             MPX_DEBUG1("Unable to print table");
       
  1934                             }
       
  1935                         }
       
  1936                     }
       
  1937                 tableNames.Close();
       
  1938                 }
       
  1939             }
       
  1940         }
       
  1941 #endif
       
  1942     }
       
  1943 
       
  1944 // ----------------------------------------------------------------------------
       
  1945 // Prints all the tables on the main and attached drives
       
  1946 // ----------------------------------------------------------------------------
       
  1947 //
       
  1948 EXPORT_C RFs& CMPXDbManager::Fs()
       
  1949     {
       
  1950     return iFs;
       
  1951     }
       
  1952 
       
  1953 
       
  1954 
       
  1955 // ---------------------------------------------------------------------------
       
  1956 // CMPXDbManager::IsRemoteDrive
       
  1957 // ---------------------------------------------------------------------------
       
  1958 //
       
  1959 EXPORT_C TBool CMPXDbManager::IsRemoteDrive(TDriveNumber aDrive)
       
  1960     {
       
  1961     TDriveInfo driveInfo;
       
  1962     TBool isRemoteDrive(EFalse);
       
  1963     if (iFs.Drive(driveInfo, aDrive) == KErrNone)
       
  1964         {
       
  1965         isRemoteDrive = driveInfo.iDriveAtt & KDriveAttRemote;
       
  1966         }
       
  1967     return isRemoteDrive;
       
  1968     }
       
  1969 
       
  1970 // ---------------------------------------------------------------------------
       
  1971 // CMPXDbManager::DoCreateDatabaseL
       
  1972 // ---------------------------------------------------------------------------
       
  1973 //
       
  1974 void CMPXDbManager::DoCreateDatabaseL( TDriveUnit aDrive )
       
  1975     {
       
  1976 	MPX_FUNC( "CMPXDbManager::DoCreateDatabaseL" );
       
  1977 	
       
  1978     RSqlDatabase database;
       
  1979     CleanupClosePushL(database);
       
  1980 
       
  1981     HBufC* filename = CreateFilenameL(aDrive);
       
  1982     CleanupStack::PushL(filename);
       
  1983     
       
  1984     // remove old databases before creating/replacing new database
       
  1985     TInt driveNameLen = aDrive.Name().Length();
       
  1986     
       
  1987     TFileName dbFileName(aDrive.Name()); //initialise with drive name        
       
  1988     dbFileName.Append(KDBFilePath);  // append private path
       
  1989     
       
  1990     //append file name
       
  1991     dbFileName.Append(filename->Right((filename->Length())- driveNameLen));     
       
  1992     
       
  1993     // locate the offset position where version info starts in file name
       
  1994     TInt pos = dbFileName.LocateReverse('v');
       
  1995 
       
  1996     //replace version info with wildcards 
       
  1997     dbFileName.Replace(pos, (dbFileName.Length()- pos), KDBFilePattern);
       
  1998 
       
  1999     CFileMan* fileManager = CFileMan::NewL(iFs);
       
  2000     TInt ret = fileManager->Delete(dbFileName);
       
  2001     delete fileManager;
       
  2002     fileManager = NULL;
       
  2003     
       
  2004     // create the database now
       
  2005     RSqlSecurityPolicy securityPolicy;
       
  2006     CleanupClosePushL(securityPolicy);
       
  2007 
       
  2008     TSecurityPolicy policy(TSecurityPolicy::EAlwaysPass);
       
  2009     securityPolicy.Create(policy);
       
  2010 
       
  2011     TSecurityPolicy schemaPolicy(TSecurityPolicy::EAlwaysPass);
       
  2012     TSecurityPolicy readPolicy(TSecurityPolicy::EAlwaysPass);
       
  2013     TSecurityPolicy writePolicy(TSecurityPolicy::EAlwaysPass);
       
  2014 
       
  2015     User::LeaveIfError(securityPolicy.SetDbPolicy(RSqlSecurityPolicy::ESchemaPolicy, schemaPolicy));
       
  2016     User::LeaveIfError(securityPolicy.SetDbPolicy(RSqlSecurityPolicy::EReadPolicy, readPolicy));
       
  2017     User::LeaveIfError(securityPolicy.SetDbPolicy(RSqlSecurityPolicy::EWritePolicy, writePolicy));
       
  2018 
       
  2019     
       
  2020     const TDesC8& config = KMCSqlConfig;
       
  2021     
       
  2022     TBool corrupt(EFalse);
       
  2023     TInt err = database.Create(filename->Des(), securityPolicy, &config);
       
  2024     if (KErrAlreadyExists == err)
       
  2025         {
       
  2026         MPX_DEBUG1("CMPXDbManager::DoCreateDatabaseL - could not create the database");
       
  2027 
       
  2028         // the file already exists and it is corrupted
       
  2029         // make sure we delete the file
       
  2030         User::LeaveIfError(database.Delete(*filename));
       
  2031 
       
  2032         MPX_DEBUG1("CMPXDbManager::DoCreateDatabaseL - deleted the database");
       
  2033 
       
  2034         // try again
       
  2035         err = database.Create(filename->Des(), securityPolicy, &config);
       
  2036 
       
  2037         // the database could not be opened but the file exists
       
  2038         corrupt = ETrue;
       
  2039         }
       
  2040     User::LeaveIfError(err);
       
  2041 
       
  2042     MPX_DEBUG1("CMPXDbManager::DoCreateDatabaseL - created the database");
       
  2043 
       
  2044     CleanupStack::PopAndDestroy(&securityPolicy);
       
  2045 
       
  2046     CreateTablesL(database, corrupt);
       
  2047 
       
  2048     CleanupStack::PopAndDestroy(filename);
       
  2049     CleanupStack::PopAndDestroy(&database);
       
  2050     }
       
  2051 
       
  2052 // End of File