diff -r fd64c38c277d -r b46a585f6909 phonebookengines_old/contactsmodel/cntdbdumper/src/dbsqldumper.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookengines_old/contactsmodel/cntdbdumper/src/dbsqldumper.cpp Fri Jun 11 13:29:23 2010 +0300 @@ -0,0 +1,697 @@ +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +/** + @file + @internalComponent + @released +*/ + +#include "dbsqldumper.h" +#include "dbhtmltags.h" +#include "dbsqlconstants.h" +#include +#include + +_LIT(KErrorMessage, "DBSqlDumper Failed"); +const TInt KMaxPathLength = 100; +const TInt KBufferLength = 80; + + +/** +Class constructor +*/ +CDbStructure::CDbStructure() + { + Init(); + } + +/** +Class destructor +*/ +CDbStructure::~CDbStructure() + { + iColumnsIndex.Reset(); + iNumColumns.Reset(); + } + +/** +Initialize table structure (number of tables, number of column in each table) + +*/ +void CDbStructure::Init() + { + iTablesIndex = KInitialValue; + iNumTables = KNumOfTables; + iColumnsIndex.Reset(); + iNumColumns.Reset(); + //columns in pref table + iColumnsIndex.Append(KInitialValue); + iNumColumns.Append(KNumColInPrefTable); + //columns in contact table + iColumnsIndex.Append(KInitialValue); + iNumColumns.Append(KNumColInContactTable); + //columns in group table + iColumnsIndex.Append(KInitialValue); + iNumColumns.Append(KNumColInGroupTable); + //columns in comm-address table + iColumnsIndex.Append(KInitialValue); + iNumColumns.Append(KNumColInCommTable); + } + +/** +Moves the cursor forward to the next table + +@return ETrue if the cursor can be moved to the next index or EFalse if the cursor + is already at the end +*/ +TBool CDbStructure::NextTable() + { + ++iTablesIndex; + return iTablesIndex < iNumTables; + } + +/** +Return current table name in the cursor + +*/ +const TDesC& CDbStructure::TableName() + { + return TableName(iTablesIndex); + } + +/** +Returns name of the table located at specified position in the table array + +*/ +const TDesC& CDbStructure::TableName(TInt aTableIndex) + { + switch(aTableIndex) + { + case EContactPrefTableName: + { + return KSqlContactPrefTableName; + } + case EContactTableName: + { + return KSqlContactTableName; + } + case EContactGroupTableName: + { + return KSqlContactGroupTableName; + } + case EContactCommAddressTableName: + { + return KSqlContactCommAddrTableName; + } + default: + { + return KNullText; + } + } + } + +/** +Moves the cursor forward to the next column in the specified table + +@return ETrue if the cursor can be moved to the next index or EFalse if the cursor + is already at the end +*/ +TBool CDbStructure::NextColumn(TInt aTableIndex) + { + ++iColumnsIndex[aTableIndex]; + return iColumnsIndex[aTableIndex] < iNumColumns[aTableIndex]; + } + +/** +Return current column name for the specified table + +@param aTableIndex table index for which column name has to be returned +*/ +const TDesC& CDbStructure::Column(TInt aTableIndex) + { + return Column(aTableIndex, iColumnsIndex[aTableIndex]); + } + +/** +Return name of the column located at specified pozition in the specified table + +*/ +const TDesC& CDbStructure::Column(TInt aTableIndex, TInt aColumnIndex) + { + switch(aTableIndex) + { + case EContactPrefTableName: //columns in preference table + switch(aColumnIndex) + { + case 0: + { + return KPrefPrefId; + } + case 1: + { + return KPrefSchemaVersion; + } + case 2: + { + return KPrefDatabaseUid; + } + case 3: + { + return KPrefPrefCreationDate; + } + case 4: + { + return KPrefMachineId; + } + case 5: + { + return KPrefPreferredOrder; + } + case 6: + { + return KPrefferredTemplateId; + } + } + break; + case EContactTableName: //columns in contact table + switch(aColumnIndex) + { + case 0: + { + return KContactId; + } + case 1: + { + return KContactTemplateId; + } + case 2: + { + return KContactTypeFlags; + } + case 3: + { + return KContactAccessCount; + } + case 4: + { + return KContactLastModified; + } + case 5: + { + return KContactGuidString; + } + case 6: + { + return KContactFirstName; + } + case 7: + { + return KContactLastName; + } + case 8: + { + return KContactCompanyName; + } + case 9: + { + return KContactFirstNamePrn; + } + case 10: + { + return KContactLastNamePrn; + } + case 11: + { + return KContactCompanyNamePrn; + } + case 12: + { + return KContactTextFieldHeader; + } + case 13: + { + return KContactBinaryFieldHeader; + } + case 14: + { + return KContactTextFields; + } + case 15: + { + return KContactBinaryFields; + } + } + break; + case EContactGroupTableName: //columns in group table + switch(aColumnIndex) + { + case 0: + { + return KGroupContactGroupId; + } + case 1: + { + return KGroupContactGroupId; + } + case 2: + { + return KGroupContactGroupMemberId; + } + } + break; + case EContactCommAddressTableName: //columns in comm-address table + switch(aColumnIndex) + { + case 0: + { + return KCommAddrId; + } + case 1: + { + return KCommAddrType; + } + case 2: + { + return KCommAddrValue; + } + case 3: + { + return KCommAddrExtraValue; + } + case 4: + { + return KCommAddrContactId; + } + } + break; + } + return KNullText; + } + +/** +Check if current column is the last column + +*/ +TBool CDbStructure::IsLastColumn(TInt aTableIndex) + { + return iColumnsIndex[aTableIndex] == (iNumColumns[aTableIndex]-1); + } + +/** +Return number of columns specified table has + +*/ +TInt CDbStructure::ColumnNo(TInt aTableIndex) + { + return iNumColumns[aTableIndex]; + } + +/** +Class destructor + +*/ +CDbSqlDumper::~CDbSqlDumper() + { + delete iBuffer; + iTableNames.Reset(); + iFile.Close(); + iDatabase.Close(); + iFsSession.Close(); + delete iDbStructure; + } + +/** +Second phase constructor for CDbSqlDumper class + +@param aDbName name of the database to be dumped. +@param aOutputDir directory where html file will be generated +*/ +void CDbSqlDumper::ConstructL(const TDesC& aDbName, const TDesC& aOutputDir) + { + // Output File Name + _LIT(KOutputFile,"DbDump.html"); + TBuf path(aOutputDir); + path.Append(KOutputFile); + + User::LeaveIfError(iFsSession.Connect() ); + iDatabase.OpenL(aDbName); + + User::LeaveIfError(iFile.Replace(iFsSession, path, EFileWrite) ); + + iBuffer = HBufC8::NewL(KBufferLength); + iDbStructure = new (ELeave) CDbStructure(); + while(iDbStructure->NextTable()) + { + iTableNames.AppendL(&(iDbStructure->TableName())); + } + } + +/** +Return a concrete CDbSqlDumper object + +@param aDbName name of the database to be dumped. +@param aOutputDir directory where html file will be generated +*/ +CDbSqlDumper* CDbSqlDumper::NewLC(const TDesC& aDbName, const TDesC& aOutputDir) + { + CDbSqlDumper* self = new (ELeave) CDbSqlDumper(); + CleanupStack::PushL(self); + self->ConstructL(aDbName, aOutputDir); + return self; + } + +/** +Utility method used to build sql string. The result sql string will be +used to select from specified table + +@param aTableIndex table index in the table array +*/ +void CDbSqlDumper::PrepareSQLStatementL(TInt aTableIndex) + { + //calculate the space needed to build the saq string + iDbStructure->Init(); + TInt size = KSQLSelect().Size(); + while(iDbStructure->NextColumn(aTableIndex)) + { + size += iDbStructure->Column(aTableIndex).Size() + 1; + } + size += KFrom().Size() + iDbStructure->TableName(aTableIndex).Size(); + + HBufC* sqlString = HBufC::NewLC( size ); + + TPtr buffer = sqlString->Des(); + + iDbStructure->Init(); + buffer.Append(KSQLSelect); + while(iDbStructure->NextColumn(aTableIndex)) + { + buffer.Append(iDbStructure->Column(aTableIndex)); + if(!iDbStructure->IsLastColumn(aTableIndex)) + { + buffer.Append(KComma); + } + else + { + buffer.Append(KSpace); + } + } + buffer.Append(KFrom); + buffer.Append(iDbStructure->TableName(aTableIndex) ); + User::LeaveIfError(iSqlStatement.Prepare(iDatabase, buffer)); + + CleanupStack::PopAndDestroy(sqlString); + } + +/** +Outputs one table values. Fetch all selected rows and output them in the +html file + +@param aTableIndex table index in the table array +@leave if there is an error at sql level, it will be forwarded +*/ +void CDbSqlDumper::OutputTableToFileL(TInt aTableIndex) + { + TInt err; + iFile.Write(KTable); + OutputTableNameToFile(aTableIndex); + OutputTableColHeadingsToFile(aTableIndex); + PrepareSQLStatementL(aTableIndex); + + // output the table's rows + while ((err =iSqlStatement.Next()) == KSqlAtRow ) + { + iFile.Write(KRow); + OutputTableColDataToFileL(aTableIndex); + iFile.Write(KRowEnd); + } + + // check if there were any error + if(err != KSqlAtEnd) + { + iSqlStatement.Close(); + User::Leave(err); + } + + iSqlStatement.Close(); + iFile.Write(KTableEnd); + } + +/** +Outputs the table name in the html file + +@param aTableIndex table index in the table array + +*/ +void CDbSqlDumper::OutputTableNameToFile(TInt aTableIndex) + { + iFile.Write(KBold); + iBuffer->Des().Copy( *(iTableNames[aTableIndex]) ); // write iTableNames[aTableIndex] to the file. + iFile.Write(*iBuffer); + iFile.Write(KBoldEnd); + } + +/** +Outputs the header of the tables created in the html file. +Header will contain column names + +@param aTableIndex table index in the table array + +*/ +void CDbSqlDumper::OutputTableColHeadingsToFile(TInt aTableIndex) + { + iFile.Write(KHdRow); + + iDbStructure->Init(); + while(iDbStructure->NextColumn(aTableIndex)) + { + iFile.Write(KCell); + iBuffer->Des().Copy(iDbStructure->Column(aTableIndex)); + iFile.Write(*iBuffer); + iFile.Write(KCellEnd); + } + + iFile.Write(KRowEnd); + } + +/** +Outputs one row of a tables data. + +@param aTableIndex table index in the table array + +*/ +void CDbSqlDumper::OutputTableColDataToFileL(TInt aTableIndex) + { + TInt counter = 0; + const TInt KNumberOfCols( iDbStructure->ColumnNo(aTableIndex) ); + + // cols are from 1, to maxCols. not from 0 to KNumberOfCols-1. + for (counter = 0; counter < KNumberOfCols; ++counter) // for each column value in this row + { + iFile.Write(KCell); + + if (iSqlStatement.IsNull(counter) ) + { + iBuffer->Des().Format(KNullCol); // write out 'NULL' to the file + } + else + { + switch ( iSqlStatement.ColumnType(counter) ) + { + case ESqlInt: + { + TInt32 val = iSqlStatement.ColumnInt(counter); + iBuffer->Des().Format(KInt32String, val); + } + break; + case ESqlInt64: + { + TInt64 val = iSqlStatement.ColumnInt64(counter); + iBuffer->Des().Format(KUInt64String, I64HIGH(val), I64LOW(val) ); + } + break; + case ESqlReal: + { + TReal32 val = iSqlStatement.ColumnReal(counter); + iBuffer->Des().Format(KRealString, val); + } + break; + case ESqlText: + { + iBuffer->Des().Copy(iSqlStatement.ColumnTextL(counter)); + } + break; + case ESqlBinary: + if ((iDbStructure->Column(aTableIndex, counter) == KContactTextFieldHeader) || + (iDbStructure->Column(aTableIndex, counter) == KContactBinaryFieldHeader)) + { + FieldHeaderColL(counter); + } + else + { + LongBinaryL(counter); + } + break; + default: + iBuffer->Des().Format(KUnknownMessage); + break; + } // switch + } // if + + iFile.Write(*iBuffer); + iFile.Write(KCellEnd); + + } // for + } + +/** +Outputs a binary column/value representing header fields + +@param aFieldIndex column index in the curently executed sql statement + +*/ +void CDbSqlDumper::FieldHeaderColL(TInt aFieldIndex) + { + TAutoClose headerBlob; + TAutoClose stream; + + headerBlob.iObj.ColumnBinary(iSqlStatement, aFieldIndex); + CEmbeddedStore* headerStore = CEmbeddedStore::FromLC(headerBlob.iObj); + stream.iObj.OpenLC(*headerStore, headerStore->Root()); + + DumpStreamL(stream.iObj); + + CleanupStack::PopAndDestroy(&stream.iObj); //OpenLC + CleanupStack::PopAndDestroy(headerStore); + } + +/** +Outputs a binary column/value representing binaryfields + +@param aFieldIndex column index in the curently executed sql statement + +*/ +void CDbSqlDumper::LongBinaryL(TInt aFieldIndex) + { + TAutoClose rdStream; + rdStream.iObj.ColumnBinary(iSqlStatement,aFieldIndex); + + DumpStreamL(rdStream.iObj); + } + +/** +Utility method used to read from a read stream and write to file + +@param stream RReadStream from which information will be read + +*/ +void CDbSqlDumper::DumpStreamL(RReadStream& stream) + { + const TInt KStreamSize = stream.Source()->SizeL(); + + iFile.Write(KDumpFont); + + _LIT8(KSizeMessage, "size is %d
"); + _LIT8(KEightSpaces, " "); + _LIT8(KByteFormat, "%02x "); + _LIT8(KFormatString, "%S 
\r\n"); + + iBuffer->Des().Format(KSizeMessage, KStreamSize); + iFile.Write(*iBuffer); + + TBuf8<8> str(KEightSpaces); //Reserve 8 symbols + + TInt counter(0); + while (counter < KStreamSize) + { + for(TInt i=0; i < 8; ++i) + { + if (counter >= KStreamSize) + { + break; + } + //format the bynary value to a printable char + TInt8 byte( stream.ReadInt8L() ); + iBuffer->Des().Format(KByteFormat, byte); + iFile.Write(*iBuffer); + + str[i] = (byte>32 ? byte : '.'); + ++counter; + } + iBuffer->Des().Format(KFormatString, &str); + iFile.Write(*iBuffer); + } + + iFile.Write(KDumpFontEnd); + } + +/** +Output database content to a file + +*/ +void CDbSqlDumper::OutputDBContentsL() + { + // Output Title + _LIT8(KHdr,"

Contacts Model DB Dump:

"); + iFile.Write(KHdr); + + TInt counter = 0; + const TInt KNumTables( iTableNames.Count() ); + + // for each table - output all tables + for (counter = 0; counter < KNumTables; ++counter) + { + OutputTableToFileL(counter); + } + } + +void RunDumpL() + { +// Location of Output Directory. (File will be called DbDump.html). Final "\" required on path. +_LIT(KOutputDir, "?:\\"); +TBuf outputDir(KOutputDir); +outputDir[0] = (TUint8) RFs::GetSystemDriveChar(); + +// Location of Contacts DB +_LIT(KDBName, "?:\\private\\10003A73\\SQLite__contacts.cdb"); +TBuf fileDBName(KDBName); +fileDBName[0] = (TUint8) RFs::GetSystemDriveChar(); + + // dump sql database + CDbSqlDumper* sqlDumper = CDbSqlDumper::NewLC(fileDBName, outputDir); + sqlDumper->OutputDBContentsL(); + CleanupStack::PopAndDestroy(sqlDumper); + } + +GLDEF_C TInt E32Main() + { + __UHEAP_MARK; + CActiveScheduler* scheduler = new CActiveScheduler; + if (scheduler) + { + CActiveScheduler::Install(scheduler); + CTrapCleanup* cleanup = CTrapCleanup::New(); + if (cleanup) + { + TRAPD(err,RunDumpL() ); + __ASSERT_ALWAYS(err == KErrNone, User::Panic(KErrorMessage,err) ); + delete cleanup; + } + delete scheduler; + } + __UHEAP_MARKEND; + return KErrNone; + } +