metadataengine/server/src/mdssqliteconnection.cpp
changeset 0 c53acadfccc6
child 14 646a02f170b9
equal deleted inserted replaced
-1:000000000000 0:c53acadfccc6
       
     1 /*
       
     2 * Copyright (c) 2002-2009 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:  Adaptation layer to SQLite database*
       
    15 */
       
    16 
       
    17 // INCLUDE FILES
       
    18 #include "mdssqliteconnection.h"
       
    19 #include "mdslogger.h"
       
    20 
       
    21 __USES_LOGGER
       
    22 
       
    23 CMdSSqLiteConnection* CMdSSqLiteConnection::NewL()
       
    24     {    
       
    25     CMdSSqLiteConnection* self = CMdSSqLiteConnection::NewLC();
       
    26     CleanupStack::Pop( self );
       
    27     return self;
       
    28     }
       
    29 
       
    30 
       
    31 CMdSSqLiteConnection* CMdSSqLiteConnection::NewLC()
       
    32     {
       
    33     CMdSSqLiteConnection* self = new ( ELeave ) CMdSSqLiteConnection( );
       
    34     CleanupStack::PushL( self );
       
    35     self->ConstructL( );
       
    36     return self;  
       
    37     }
       
    38 
       
    39 
       
    40 CMdSSqLiteConnection::CMdSSqLiteConnection()
       
    41 	: iDbFileName( NULL ), iEnableTransaction( ETrue ),iNotFinishFindQuery( NULL )
       
    42     {
       
    43     }
       
    44 
       
    45 
       
    46 CMdSSqLiteConnection::~CMdSSqLiteConnection()
       
    47     {
       
    48     CloseDb();
       
    49 
       
    50     delete iDbFileName;
       
    51 
       
    52     iNotFinishFindQuery = NULL;
       
    53     }
       
    54 
       
    55 void CMdSSqLiteConnection::DeleteDb( TDesC16* aName )
       
    56 	{
       
    57 	if( aName )
       
    58 		{
       
    59 		RSqlDatabase::Delete( *aName );
       
    60 		}
       
    61 	else
       
    62 		{
       
    63 		RSqlDatabase::Delete( KMdsSqlDbDefaultName );
       
    64 		}
       
    65 	}
       
    66 
       
    67 void CMdSSqLiteConnection::CloseDb()
       
    68 	{
       
    69 	iMdeSqlDb.Close();
       
    70 	}
       
    71 
       
    72 void CMdSSqLiteConnection::ConstructL()
       
    73     {
       
    74     }
       
    75 
       
    76 void CMdSSqLiteConnection::OpenDbL( const TDesC& aDbFileName )
       
    77     {
       
    78     _LIT8( KMdsSqlDbaConfig, "cache_size=10000; page_size=4096; encoding=\"UTF-16\";");
       
    79 
       
    80     TInt err = KErrNone;
       
    81 
       
    82     delete iDbFileName;
       
    83     iDbFileName = NULL; // in case AllocL leaves
       
    84     iDbFileName = aDbFileName.AllocL();
       
    85 
       
    86     // we need to set up policy, because we use secure database
       
    87 	TSecurityPolicy defaultPolicy(TSecurityPolicy::EAlwaysPass);
       
    88     RSqlSecurityPolicy sqlSecurityPolicy;
       
    89     CleanupClosePushL( sqlSecurityPolicy );
       
    90     err = sqlSecurityPolicy.Create( defaultPolicy );
       
    91 
       
    92     if ( err != KErrNone )
       
    93     	{
       
    94     	_LIT( KMdsSecurityCheckFail, "Security check fail" );
       
    95     	TraceAndLeaveL( KMdsSecurityCheckFail, err );
       
    96     	}
       
    97     /**
       
    98      * Open database:
       
    99      *   First we try to create new db. If this fails check if db already exists and
       
   100      *   try to open it. Otherwise we cannot open it and we leave
       
   101      */
       
   102     err = iMdeSqlDb.Create( *iDbFileName, sqlSecurityPolicy, &KMdsSqlDbaConfig );
       
   103     if ( err != KErrNone )
       
   104     	{
       
   105     	// it could fail because database exists
       
   106     	if ( err == KErrAlreadyExists )
       
   107     		{
       
   108     		err = iMdeSqlDb.Open( *iDbFileName, &KMdsSqlDbaConfig );
       
   109     		if ( err != KErrNone )
       
   110     			{
       
   111     			__LOG1( ELogDb, "Cannot open database %d", err );
       
   112     			}
       
   113     		}
       
   114     	else 
       
   115     		{
       
   116     		__LOG1( ELogDb, "Unknown error while creating %d", err );
       
   117     		}
       
   118 
       
   119     	User::LeaveIfError( err );
       
   120     	}
       
   121     CleanupStack::PopAndDestroy( &sqlSecurityPolicy );
       
   122     }
       
   123 
       
   124 TInt CMdSSqLiteConnection::ExecuteL( const TDesC& aCommand,
       
   125                                      const RRowData& aVariables,
       
   126                                      RMdsStatement* aStatement )
       
   127     {
       
   128     TInt err = KErrNone;
       
   129 
       
   130     if ( aVariables.Size() == 0 )
       
   131         {
       
   132         // no variables
       
   133         err = iMdeSqlDb.Exec( aCommand );
       
   134 
       
   135 		if ( err < KErrNone )
       
   136         	{
       
   137             _LIT( KMdSExec, "Exec (no variables)" );
       
   138             TraceAndLeaveL( KMdSExec, err );
       
   139             }
       
   140 		}
       
   141     else if ( aStatement )
       
   142     	{
       
   143         if ( aStatement->iPrepared == EFalse )
       
   144             {
       
   145             err = aStatement->iStatement.Prepare( iMdeSqlDb, aCommand );
       
   146 
       
   147         	if ( err < KErrNone )
       
   148                 {
       
   149                 _LIT( KMdSPrepare, "Prepare" );
       
   150                 TraceAndLeaveL( KMdSPrepare, err );
       
   151                 }
       
   152             aStatement->iPrepared = ETrue;
       
   153             }
       
   154         else
       
   155             {
       
   156             err = aStatement->iStatement.Reset();
       
   157          	if ( err < KErrNone )
       
   158                 {
       
   159                 _LIT( KMdSResume, "Resume" );
       
   160                 TraceAndLeaveL( KMdSResume, err );
       
   161                 }
       
   162             }
       
   163            
       
   164         DoBindL( aStatement->iStatement, aVariables );
       
   165         err = aStatement->iStatement.Exec();
       
   166 
       
   167         if ( err < KErrNone )
       
   168             {
       
   169             aStatement->iStatement.Reset();
       
   170             aStatement->iPrepared = EFalse;
       
   171 			_LIT( KMdSExec, "Exec" );
       
   172             TraceAndLeaveL( KMdSExec, err );
       
   173             }
       
   174     	}
       
   175     else
       
   176         {
       
   177         RSqlStatement mdeSqlDbStmt;
       
   178         CleanupClosePushL( mdeSqlDbStmt );
       
   179         err = mdeSqlDbStmt.Prepare( iMdeSqlDb, aCommand );
       
   180 
       
   181         if ( err < KErrNone )
       
   182             {
       
   183             _LIT( KMdsPrepare, "Prepare (no statement)" );
       
   184             TraceAndLeaveL( KMdsPrepare, err );
       
   185             }
       
   186 
       
   187         DoBindL( mdeSqlDbStmt, aVariables );
       
   188         
       
   189         err = mdeSqlDbStmt.Exec();
       
   190 
       
   191         if ( err < KErrNone )
       
   192             {
       
   193             _LIT( KMdsExec, "Exec (no statement)" );
       
   194             TraceAndLeaveL( KMdsExec, err );
       
   195             }
       
   196 
       
   197         CleanupStack::PopAndDestroy( &mdeSqlDbStmt );
       
   198         }
       
   199     return err;
       
   200     }
       
   201 
       
   202 void CMdSSqLiteConnection::ExecuteQueryL( const TDesC& aQuery,
       
   203 										  RMdsStatement& aStatement,
       
   204 										  const RRowData& aVariables )
       
   205     {
       
   206     TInt stmterr;
       
   207     if ( aStatement.iPrepared == EFalse )
       
   208     	{
       
   209     	stmterr = aStatement.iStatement.Prepare( iMdeSqlDb, aQuery );
       
   210     	if ( stmterr != KErrNone )
       
   211         	{
       
   212         	_LIT( KMdSQueryPrepare, "Query Prepare" );
       
   213         	TraceAndLeaveL( KMdSQueryPrepare, stmterr );
       
   214         	}
       
   215     	aStatement.iPrepared = ETrue;
       
   216     	}
       
   217     else
       
   218     	{
       
   219     	stmterr = aStatement.iStatement.Reset();
       
   220     	if ( stmterr != KErrNone )
       
   221         	{
       
   222         	_LIT( KMdSQueryReset, "Query Reset" );
       
   223         	TraceAndLeaveL( KMdSQueryReset, stmterr );
       
   224         	}
       
   225     	}
       
   226         
       
   227     DoBindL( aStatement.iStatement, aVariables );
       
   228     }
       
   229 
       
   230 void CMdSSqLiteConnection::DoBindL( RSqlStatement& aStatement, const RRowData& aVariables )
       
   231     {
       
   232     const TInt count( aVariables.Size() );
       
   233     for( TInt i=0; i < count; ++i )
       
   234         {
       
   235         switch ( aVariables.Column( i ).Type() )
       
   236             {
       
   237             case EColumnInt32:
       
   238                 {
       
   239                 TInt32 val = 0;
       
   240                 aVariables.Column( i ).Get( val );
       
   241                 aStatement.BindInt( i, val );
       
   242                 break;
       
   243                 }
       
   244             case EColumnUint32:
       
   245                 {
       
   246                 TUint32 val = 0;
       
   247                 aVariables.Column( i ).Get( val );
       
   248                 aStatement.BindInt64( i, (TInt64)val ); 
       
   249                 break;
       
   250                 }
       
   251             case EColumnBool:
       
   252                 {
       
   253                 TBool val = 0;
       
   254                 aVariables.Column( i ).Get( val );
       
   255                 aStatement.BindInt( i, val );
       
   256                 break;
       
   257                 }
       
   258             case EColumnInt64:
       
   259                 {
       
   260                 TInt64 val = 0;
       
   261                 aVariables.Column( i ).Get( val );
       
   262                 aStatement.BindInt64( i, val );
       
   263                 break;
       
   264                 }
       
   265             case EColumnReal32:
       
   266                 {
       
   267                 TReal32 val = 0;
       
   268                 aVariables.Column( i ).Get( val );
       
   269                 aStatement.BindReal( i, val );
       
   270                 break;
       
   271                 }
       
   272             case EColumnReal64:
       
   273                 {
       
   274                 TReal64 val = 0;
       
   275                 aVariables.Column( i ).Get( val );
       
   276                 aStatement.BindReal( i, val );
       
   277                 break;
       
   278                 }
       
   279             case EColumnTime:
       
   280                 {
       
   281                 TTime val = TInt64(0);
       
   282                 aVariables.Column( i ).Get( val );
       
   283                 aStatement.BindInt64( i, val.Int64() );
       
   284                 break;
       
   285                 }
       
   286             case EColumnDes16:
       
   287                 {
       
   288                 TPtrC16 val = TPtr16((TUint16*)0, 0); //KNullPtr16;
       
   289                 aVariables.Column( i ).Get( val );
       
   290                 aStatement.BindText( i, val );
       
   291                 break;
       
   292                 }
       
   293             case EColumnNotUsed:
       
   294                 // skip this variable
       
   295                 break;
       
   296             default:
       
   297 #ifdef _DEBUG
       
   298             	User::Panic( _L( "MdSSCDoB" ), KErrCorrupt );
       
   299 #endif
       
   300                 User::Leave( KErrCorrupt );
       
   301             }
       
   302         }
       
   303     }
       
   304 
       
   305 TBool CMdSSqLiteConnection::NextRowL( RMdsStatement& aQuery, RRowData& aRow )
       
   306     {
       
   307     const TInt qerr = aQuery.iStatement.Next();
       
   308 	if ( qerr == KSqlAtEnd )
       
   309 		{
       
   310 		return EFalse;
       
   311 		}
       
   312 	else if ( qerr != KSqlAtRow )
       
   313 		{
       
   314 		_LIT( KMdsQueryNextRow, "Query NextRow" );
       
   315 		TraceAndLeaveL( KMdsQueryNextRow, qerr );
       
   316 		}
       
   317 
       
   318     // obtain column data into local storage and row data pointer
       
   319     ColumnsL( aQuery.iStatement, aRow );
       
   320 
       
   321     return ETrue;
       
   322     }
       
   323 
       
   324 void CMdSSqLiteConnection::CurrentRowL( const RMdsStatement& aQuery, RRowData& aRow )
       
   325     {
       
   326     // obtain column data into local storage and row data pointer
       
   327     if ( EFalse != aQuery.iStatement.AtRow() )
       
   328     	{
       
   329     	ColumnsL( aQuery.iStatement, aRow );
       
   330     	}
       
   331     else
       
   332     	{
       
   333     	_LIT( KMdsNoProcessableRow, "Wrong row to process" );
       
   334     	TraceAndLeaveL( KMdsNoProcessableRow, KSqlErrNotFound );
       
   335     	}
       
   336     }
       
   337 
       
   338 void CMdSSqLiteConnection::ColumnsL( const RSqlStatement& aStatement, RRowData& aRow )
       
   339     {
       
   340     const TInt count( aRow.Size() );
       
   341     for( TInt i=0; i < count; ++i )
       
   342         {
       
   343         // get data in column, check for type
       
   344    		const TSqlColumnType actual = aStatement.ColumnType( i );
       
   345    		
       
   346    		if( actual == ESqlNull )
       
   347    			{
       
   348             aRow.Column( i ).Set( (const HBufC16*)NULL );
       
   349 
       
   350             continue;
       
   351    			}
       
   352    		
       
   353         const TColumnDataType coltype = aRow.Column( i ).Type();
       
   354         switch ( coltype )
       
   355             {
       
   356             case EColumnBool:
       
   357                 {
       
   358                 TInt valInt = aStatement.ColumnInt( i );
       
   359                 const TBool valBool = valInt ? ETrue : EFalse;
       
   360                 aRow.Column( i ).Set( valBool );
       
   361                 break;
       
   362                 }
       
   363             case EColumnInt32:
       
   364                 {
       
   365                 TInt32 valInt = aStatement.ColumnInt( i );
       
   366                 aRow.Column( i ).Set( valInt );
       
   367                 break;
       
   368                 }
       
   369             case EColumnUint32:
       
   370                 {
       
   371                 TInt64 valInt64 = aStatement.ColumnInt64( i );           
       
   372                 aRow.Column( i ).Set( (TUint32)valInt64 );
       
   373                 break;
       
   374                 }
       
   375             case EColumnInt64:
       
   376                 {
       
   377                 TInt64 valInt64 = aStatement.ColumnInt64( i );
       
   378                 aRow.Column( i ).Set( valInt64 );
       
   379                 break;
       
   380                 }
       
   381             case EColumnReal32:
       
   382                 {
       
   383                 TReal valReal = aStatement.ColumnReal( i );
       
   384                 aRow.Column( i ).Set(  static_cast<TReal32>( valReal ) );
       
   385                 break;
       
   386                 }
       
   387             case EColumnReal64:
       
   388                 {
       
   389                 TReal valReal = aStatement.ColumnReal( i );
       
   390                 aRow.Column( i ).Set( valReal );
       
   391                 break;
       
   392                 }
       
   393             case EColumnTime:
       
   394                 {
       
   395                 TTime valTime = aStatement.ColumnInt64( i );
       
   396                 aRow.Column( i ).Set( valTime );
       
   397                 break;
       
   398                 }
       
   399            	case EColumnDes16:
       
   400            		{
       
   401            		switch ( actual )
       
   402            		{
       
   403            		case ESqlText:
       
   404                     {
       
   405                     TPtrC16 valTPtrC16 = aStatement.ColumnTextL( i );
       
   406                     HBufC16* valHBuf16 = HBufC16::NewL( valTPtrC16.Length() );
       
   407                     *valHBuf16 = valTPtrC16;
       
   408                 	aRow.Column( i ).Set( valHBuf16 );
       
   409                 	break;
       
   410                     }
       
   411            		case ESqlInt:
       
   412                     {
       
   413                     HBufC16* valHBuf16int32 = HBufC16::NewL( 30 );
       
   414                     TInt valInt = aStatement.ColumnInt( i );
       
   415                     valHBuf16int32->Des().Num( valInt );
       
   416                     aRow.Column( i ).Set( valHBuf16int32 );
       
   417                     break;
       
   418                     }
       
   419            		case ESqlInt64:
       
   420                     {
       
   421                     HBufC16* valHBuf16int64 = HBufC16::NewL( 30 );
       
   422                 	TInt64 valInt64 = aStatement.ColumnInt64( i );
       
   423                     valHBuf16int64->Des().Num( valInt64 );
       
   424                     aRow.Column( i ).Set( valHBuf16int64 );
       
   425                     break;
       
   426                     }
       
   427            		case ESqlReal:
       
   428                     {
       
   429                     HBufC16* valHBuf16real64 = HBufC16::NewL( 40 );
       
   430                 	TReal valReal = aStatement.ColumnReal( i );
       
   431                 	TRealFormat realFormat;
       
   432                 	realFormat.iType |= KAllowThreeDigitExp;
       
   433                     valHBuf16real64->Des().Num( valReal, realFormat );
       
   434                     aRow.Column( i ).Set( valHBuf16real64 );
       
   435                     break;
       
   436                     }
       
   437            		case ESqlNull:
       
   438                     {
       
   439                     aRow.Column( i ).Set( (HBufC16*)NULL );
       
   440                     break;
       
   441                     }
       
   442            		default:
       
   443                     {
       
   444 #ifdef _DEBUG
       
   445             		User::Panic( _L( "MdSSCCo1" ), KErrCorrupt );
       
   446 #endif
       
   447                     User::Leave( KErrCorrupt );
       
   448                     }
       
   449            		}
       
   450            		
       
   451                 break;
       
   452                 }
       
   453             case EColumnNotUsed:
       
   454                 // skip this round
       
   455                 break;
       
   456 
       
   457             default:
       
   458 #ifdef _DEBUG
       
   459 				User::Panic( _L( "MdSSCCo2" ), KErrCorrupt );
       
   460 #endif
       
   461 				User::Leave( KErrCorrupt );
       
   462             }
       
   463         }
       
   464     }
       
   465 
       
   466 void CMdSSqLiteConnection::Terminate( RMdsStatement& aQuery )
       
   467     {    
       
   468     aQuery.Close();
       
   469     EnableTransaction( ETrue, aQuery );
       
   470     }
       
   471 
       
   472 void CMdSSqLiteConnection::TransactionBeginL()
       
   473     {
       
   474     if ( !iEnableTransaction || iMdeSqlDb.InTransaction() )
       
   475         {
       
   476         return;
       
   477         }
       
   478     iEnableTransaction = EFalse;
       
   479     iTransactionOngoing = ETrue;
       
   480     _LIT(KBeginTransaction, "BEGIN;");
       
   481     RRowData emptyRow;
       
   482     CleanupClosePushL( emptyRow );
       
   483     TRAPD( err, ExecuteL(KBeginTransaction, emptyRow) );
       
   484     if (err != KErrNone)
       
   485     	{
       
   486     	_LIT( KMdsTransactionBegin, "Transaction begin error" );
       
   487     	TraceAndLeaveL( KMdsTransactionBegin, err );
       
   488     	}
       
   489 	CleanupStack::PopAndDestroy( &emptyRow );
       
   490     }
       
   491 
       
   492 void CMdSSqLiteConnection::TransactionCommitL()
       
   493     {
       
   494     if ( !iTransactionOngoing )
       
   495         {
       
   496         return;
       
   497         }
       
   498     _LIT(KCommit, "COMMIT;");
       
   499     RRowData emptyRow;
       
   500     CleanupClosePushL( emptyRow );
       
   501     TRAPD( err, ExecuteL(KCommit, emptyRow) );
       
   502     if (err != KErrNone)
       
   503     	{
       
   504     	_LIT( KMdsTransactionCommit, "Transaction commit error" );
       
   505     	TraceAndLeaveL( KMdsTransactionCommit, err );
       
   506     	}
       
   507     if( !iNotFinishFindQuery )
       
   508         {
       
   509         iEnableTransaction = ETrue;
       
   510         }
       
   511     iTransactionOngoing = EFalse;
       
   512 	CleanupStack::PopAndDestroy( &emptyRow );
       
   513     }
       
   514 
       
   515 void CMdSSqLiteConnection::TransactionRollbackL()
       
   516     {
       
   517     if ( !iTransactionOngoing )
       
   518         {
       
   519         return;
       
   520         }
       
   521     _LIT(KRollback, "ROLLBACK;");
       
   522     RRowData emptyRow;
       
   523     CleanupClosePushL( emptyRow );
       
   524     TRAPD( err, ExecuteL(KRollback, emptyRow) );
       
   525     if( !iNotFinishFindQuery )
       
   526         {
       
   527         iEnableTransaction = ETrue;
       
   528         }
       
   529     iTransactionOngoing = EFalse;
       
   530     if (err != KErrNone)
       
   531     	{
       
   532     	_LIT( KMdsTransactionRollback, "Transaction rollback error" );
       
   533     	TraceAndLeaveL( KMdsTransactionRollback, err );
       
   534     	}
       
   535 	CleanupStack::PopAndDestroy( &emptyRow );
       
   536     }
       
   537 
       
   538 #ifdef _DEBUG
       
   539 void CMdSSqLiteConnection::TraceAndLeaveL( const TDesC& aFailedCommand, TInt aSqliteError )
       
   540     {
       
   541 	TPtrC errorMsg = iMdeSqlDb.LastErrorMessage();
       
   542     if ( aFailedCommand.Length() > 0 )
       
   543         {
       
   544         __LOG2( ELogDb, "%S %d", &aFailedCommand, aSqliteError );
       
   545         }
       
   546 	__LOG1( ELogDb, "SQLiteError description: %S", &errorMsg );
       
   547     User::Leave( aSqliteError );
       
   548     }
       
   549 #else
       
   550 void CMdSSqLiteConnection::TraceAndLeaveL( const TDesC& /*aFailedCommand*/, TInt aSqliteError )
       
   551     {
       
   552     User::Leave( aSqliteError );
       
   553     }
       
   554 #endif
       
   555 
       
   556 const TDesC& CMdSSqLiteConnection::DbFileName() const
       
   557 	{
       
   558 	return *iDbFileName;
       
   559 	}
       
   560 
       
   561 void CMdSSqLiteConnection::EnableTransaction( TBool aEnable, RMdsStatement& aQuery ) 
       
   562     {
       
   563     if( aEnable )
       
   564         {
       
   565         // check whether current query is the query which disabled the transaction when enabling transaction
       
   566         if( !iEnableTransaction && ( iNotFinishFindQuery == &aQuery ) )
       
   567             {
       
   568             if( !iTransactionOngoing )
       
   569                 {
       
   570                 iEnableTransaction = aEnable;
       
   571                 }
       
   572             iNotFinishFindQuery = NULL;
       
   573             }
       
   574         }
       
   575     else
       
   576         {
       
   577         iEnableTransaction = aEnable;
       
   578         // save current find operation which will continue when diable transaction
       
   579         iNotFinishFindQuery = &aQuery;
       
   580         }
       
   581     }
       
   582