--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/cntdbdumper/src/dbsqldumper.cpp Tue Feb 02 10:12:17 2010 +0200
@@ -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 <e32test.h>
+#include <s32mem.h>
+
+_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<KMaxPathLength> 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<RSqlColumnReadStream> headerBlob;
+ TAutoClose<RStoreReadStream> 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<RSqlColumnReadStream> 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 <BR>");
+ _LIT8(KEightSpaces, " ");
+ _LIT8(KByteFormat, "%02x ");
+ _LIT8(KFormatString, "%S <BR>\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,"<H2>Contacts Model DB Dump:</H2>");
+ 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<sizeof(KOutputDir)> outputDir(KOutputDir);
+outputDir[0] = (TUint8) RFs::GetSystemDriveChar();
+
+// Location of Contacts DB
+_LIT(KDBName, "?:\\private\\10003A73\\SQLite__contacts.cdb");
+TBuf<sizeof(KDBName)> 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;
+ }
+