diff -r 000000000000 -r 2e3d3ce01487 tzservices/tzserver/Server/Source/tzuserdata.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tzservices/tzserver/Server/Source/tzuserdata.cpp Tue Feb 02 10:12:00 2010 +0200 @@ -0,0 +1,1022 @@ +// Copyright (c) 2008-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: +// + +#include "tzuserdata.h" +#include +#include +#include +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#include +#endif +#include "tzidinternal.h" + +_LIT(KUserDatabaseName, "c:\\private\\1020383e\\SQLite__tzuserdata.db"); +_LIT(KTzPrivatePath, "c:\\private\\1020383e\\"); + +// Transaction constants +_LIT(KBeginTransaction,"BEGIN TRANSACTION;"); +_LIT(KCommitTransaction,"COMMIT;"); +_LIT(KRollbackTransaction,"ROLLBACK;"); + +// Tz Rules Table Parameters +_LIT(KTzRulesTblTzIdParam, ":tzId"); +_LIT(KTzRulesTblRuleTypeParam, ":ruleType"); +_LIT(KTzRulesTblDSTStartTimeParam, ":dstStartTime"); +_LIT(KTzRulesTblDSTStartRefParam, ":dstStartRef"); +_LIT(KTzRulesTblDSTEndTimeParam, ":dstEndTime"); +_LIT(KTzRulesTblDSTEndRefParam, ":dstEndRef"); +_LIT(KTzRulesTblOldOffsetParam, ":oldOffset"); +_LIT(KTzRulesTblNewOffsetParam, ":newOffset"); +_LIT(KTzRulesTblMonthParam, ":month"); +_LIT(KTzRulesTblDayParam, ":day"); +_LIT(KTzRulesTblWeekParam, ":week"); +_LIT(KTzRulesTblTimeRefParam, ":timeRef"); +_LIT(KTzRulesTblMinsParam, ":mins"); + +// Tz Rules Table Index +_LIT(KTzRulesTblRuleTypeIndex, "ruleType"); +_LIT(KTzRulesTblDSTStartTimeIndex, "dstStartTime"); +_LIT(KTzRulesTblDSTStartRefIndex, "dstStartRef"); +_LIT(KTzRulesTblDSTEndTimeIndex, "dstEndTime"); +_LIT(KTzRulesTblDSTEndRefIndex, "dstEndRef"); +_LIT(KTzRulesTblOldOffsetIndex, "oldOffset"); +_LIT(KTzRulesTblNewOffsetIndex, "newOffset"); +_LIT(KTzRulesTblMonthIndex, "month"); +_LIT(KTzRulesTblDayIndex, "day"); +_LIT(KTzRulesTblWeekIndex, "week"); +_LIT(KTzRulesTblTimeRefIndex, "timeRef"); +_LIT(KTzRulesTblMinsIndex, "mins"); + +// Tz Names Table Parameters +_LIT(KTzNamesTblTzIdParam, ":tzId"); +_LIT(KTzNamesTblStdNameParam, ":stdName"); +_LIT(KTzNamesTblShortStdNameParam, ":shortStdName"); +_LIT(KTzNamesTblDSTNameParam, ":dstName"); +_LIT(KTzNamesTblShortDSTNameParam, ":shortDstName"); +_LIT(KTzNamesTblCityNameParam, ":cityName"); +_LIT(KTzNamesTblRegionNameParam, ":regionName"); + +// Tz Names Table Index +_LIT(KTzNamesTblTzIdIndex, "tzId"); +_LIT(KTzNamesTblStdNameIndex, "stdName"); +_LIT(KTzNamesTblShortStdNameIndex, "shortStdName"); +_LIT(KTzNamesTblDSTNameIndex, "dstName"); +_LIT(KTzNamesTblShortDSTNameIndex, "shortDstName"); +_LIT(KTzNamesTblCityNameIndex, "cityName"); +_LIT(KTzNamesTblRegionNameIndex, "regionName"); + +// Identifier Table Index +_LIT(KNextTzIdentifierIndex, "nextTzId"); + +// InitialStdOffset Table Param +_LIT(KTzInitialStdOffsetTblTzIdParam, ":tzId"); +_LIT(KTzInitialStdOffsetTblStdInitialOffsetParam, ":initialStdOffset"); + +// InitialStdOffset Table Index +_LIT(KTzInitialStdOffsetTblStdInitialOffsetIndex, "initialStdOffset"); + +// Create statements +_LIT8 (KTzRulesCreateStmnt, "CREATE TABLE rules (tzId INTEGER NOT NULL, ruleType \ + INTEGER, dstStartTime INT64 NOT NULL, dstStartRef INTEGER, \ + dstEndTime INT64 NOT NULL, dstEndRef INTEGER, oldOffset \ + INTEGER NOT NULL, newOffset INTEGER NOT NULL, month INTEGER, \ + day INTEGER, week INTEGER, timeRef INTEGER, mins INTEGER NOT NULL)"); + +_LIT8 (KTzNamesCreateStmnt, "CREATE TABLE names ( tzId INTEGER NOT NULL PRIMARY \ + KEY, stdName CHAR(255), shortStdName CHAR(10), dstName \ + CHAR(255), shortDstName CHAR(10), cityName CHAR(255), \ + regionName CHAR(255))"); + +_LIT8 (KTzIdentifierCreateStmnt, "CREATE TABLE identifier ( nextTzId INTEGER NOT NULL )"); + +_LIT8 (KTzInitialStdOffsetCreateStmnt, "CREATE TABLE initialStdOffset (tzId INTEGER NOT NULL, initialStdOffset INTEGER)"); + +// Insert statements +_LIT8(KInsertRulesStmnt, "INSERT INTO rules (tzId, ruleType, dstStartTime, dstStartRef, \ + dstEndTime, dstEndRef, oldOffset, newOffset, month, day, \ + week, timeRef, mins) VALUES (:tzId, :ruleType, :dstStartTime,\ + :dstStartRef, :dstEndTime, :dstEndRef, :oldOffset, :newOffset,\ + :month, :day, :week, :timeRef, :mins)"); + +_LIT8(KInsertNamesStmnt, "INSERT INTO names(tzId, stdName, shortStdName, dstName, shortDstName,\ + cityName, regionName) VALUES(:tzId, :stdName, :shortStdName, :dstName,\ + :shortDstName, :cityName, :regionName)"); + +_LIT(KInsertIdentifierStmnt, "INSERT INTO identifier (nextTzId) VALUES (%d)"); + +_LIT8(KInsertInitialStdOffsetStmnt, "INSERT INTO initialStdOffset (tzId, initialStdOffset) \ + VALUES (:tzId, :initialStdOffset)"); + +//Select statements +_LIT8(KSelectNextTzIdStmnt, "SELECT nextTzId FROM identifier"); + +_LIT(KSelectRulesStmnt, "SELECT * FROM rules WHERE tzId = %d"); + +_LIT(KSelectRulesCountStmnt, "SELECT COUNT(tzId) FROM rules WHERE tzId = %d"); + +_LIT(KSelectNamesCountStmnt, "SELECT COUNT(tzId) FROM names WHERE tzId = %d"); + +_LIT(KSelectTzIdCountFromNamesStmnt, "SELECT COUNT(tzId) FROM names WHERE tzId = %d"); + +_LIT(KSelectNamesStmnt, "SELECT * FROM names WHERE tzId = %d"); + +_LIT(KSelectTzIdFromNamesStmnt, "SELECT tzId FROM names"); + +_LIT(KSelectInitialStdOffsetStmnt, "SELECT initialStdOffset FROM initialStdOffset WHERE tzId = %d"); + +//Update statements +_LIT (KUpdateIdentifierStmnt, "UPDATE identifier SET nextTzId = :nextTzId"); + +//Delete statements +_LIT(KDeleteRulesStmnt, "DELETE FROM rules WHERE tzId = %d"); + +_LIT(KDeleteNamesStmnt, "DELETE FROM names WHERE tzId = %d"); + +_LIT(KDeleteInitialStdOffset, "DELETE FROM initialStdOffset WHERE tzId = %d"); + +const TInt KSqlStringLength = 100; +const TUint KOutOfBoundsUserId = 0x5000; + +CTzUserDataDb* CTzUserDataDb::NewL() + { + CTzUserDataDb* self = new(ELeave) CTzUserDataDb(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CTzUserDataDb::CTzUserDataDb() + { + } + +CTzUserDataDb::~CTzUserDataDb() + { + // We don't own the pointers in this array + iChangeObservers.Close(); + iDatabase.Close(); + } + +void CTzUserDataDb::ConstructL() + { + OpenL(); + } + +void CTzUserDataDb::Close() + { + iDatabase.Close(); + } + +void CTzUserDataDb::OpenL() + { + RFs fs; + CleanupClosePushL(fs); + + // Open the database + TInt ret = iDatabase.Open(KUserDatabaseName()); + // If the database could not be opened because + // the file was not found in the path provided, create the directory + if(ret == KErrNotFound || ret == KErrPathNotFound) + { + User::LeaveIfError(fs.Connect()); + ret = fs.MkDir(KTzPrivatePath); + // If there are no errors while creating path + // or the path already exists, create the database + if(ret == KErrNone || ret == KErrAlreadyExists) + { + CreateL(); + } + } + else + { + User::LeaveIfError(ret); + } + CleanupStack::PopAndDestroy(&fs); + } + +void CTzUserDataDb::CreateL() + { + User::LeaveIfError(iDatabase.Create(KUserDatabaseName())); + iDatabase.Close(); + CreateSchemaL(); + } + +void CTzUserDataDb::CreateSchemaL() + { + RSqlStatement stmt; + CleanupClosePushL(stmt); + + User::LeaveIfError(iDatabase.Open(KUserDatabaseName())); + User::LeaveIfError(stmt.Prepare(iDatabase, KTzRulesCreateStmnt)); + User::LeaveIfError(stmt.Exec()); + stmt.Close(); + + User::LeaveIfError(stmt.Prepare(iDatabase, KTzNamesCreateStmnt)); + User::LeaveIfError(stmt.Exec()); + stmt.Close(); + + User::LeaveIfError(stmt.Prepare(iDatabase, KTzIdentifierCreateStmnt)); + User::LeaveIfError(stmt.Exec()); + stmt.Close(); + + TBuf sqlId; + sqlId.Format(KInsertIdentifierStmnt, KUserTzIdMin); + User::LeaveIfError(stmt.Prepare(iDatabase, sqlId)); + User::LeaveIfError(stmt.Exec()); + stmt.Close(); + + User::LeaveIfError(stmt.Prepare(iDatabase, KTzInitialStdOffsetCreateStmnt)); + User::LeaveIfError(stmt.Exec()); + stmt.Close(); + + CleanupStack::PopAndDestroy(&stmt); + } + +TInt CTzUserDataDb::CreateTzL(const CTzRules& aRules, const CTzUserNames& aNames) + { + if(iBackupInProgress || iRestoreInProgress) + { + User::Leave(KErrLocked); + } + + RSqlStatement stmt; + CleanupClosePushL(stmt); + + BeginTransactionL(); + + TInt err = stmt.Prepare(iDatabase, KSelectNextTzIdStmnt); + User::LeaveIfError(err); + TInt colIndex = stmt.ColumnIndex(KNextTzIdentifierIndex); + User::LeaveIfError(colIndex); + while((err = stmt.Next()) == KSqlAtRow) + { + iNextCandidateTzId = stmt.ColumnInt64(colIndex); + } + + stmt.Close(); + + // Check if the next available user ID is valid + if(iNextCandidateTzId == KOutOfBoundsUserId || IsIdInDbL(iNextCandidateTzId)) + { + iNextCandidateTzId = FindUnusedTzIdL(); + } + + // If all the user IDs have been used, leave with KErrOverflow + if(iNextCandidateTzId == KOutOfBoundsUserId) + { + User::Leave(KErrOverflow); + } + + TUint retId = iNextCandidateTzId; + TInt index; + TInt count = aRules.Count(); + for(TInt i=0; i(aRules)[i]; + + // Insert a row in the rules + User::LeaveIfError(stmt.Prepare(iDatabase, KInsertRulesStmnt())); + + index = stmt.ParameterIndex(KTzRulesTblTzIdParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindInt64(index, iNextCandidateTzId)); + index = stmt.ParameterIndex(KTzRulesTblRuleTypeParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindInt(index, rule.iDayRule)); + index = stmt.ParameterIndex(KTzRulesTblDSTStartTimeParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindInt64(index, rule.iFrom.iTime.Int64())); + index = stmt.ParameterIndex(KTzRulesTblDSTStartRefParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindInt(index, rule.iFrom.iTimeReference)); + index = stmt.ParameterIndex(KTzRulesTblDSTEndTimeParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindInt64(index, rule.iTo.iTime.Int64())); + index = stmt.ParameterIndex(KTzRulesTblDSTEndRefParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindInt(index, rule.iTo.iTimeReference)); + index = stmt.ParameterIndex(KTzRulesTblOldOffsetParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindInt(index, rule.iOldLocalTimeOffset)); + index = stmt.ParameterIndex(KTzRulesTblNewOffsetParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindInt(index, rule.iNewLocalTimeOffset)); + index = stmt.ParameterIndex(KTzRulesTblMonthParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindInt(index, rule.iMonth)); + index = stmt.ParameterIndex(KTzRulesTblDayParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindInt(index, rule.iDayOfMonth)); + index = stmt.ParameterIndex(KTzRulesTblWeekParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindInt(index, rule.iDayOfWeek)); + index = stmt.ParameterIndex(KTzRulesTblTimeRefParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindInt(index, rule.iTimeReference)); + index = stmt.ParameterIndex(KTzRulesTblMinsParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindInt(index, rule.iTimeOfChange)); + + TInt ret = stmt.Exec(); + stmt.Close(); + + if(ret < KErrNone) + { + User::Leave(ret); + } + } + + // Insert a row in the names + User::LeaveIfError(stmt.Prepare(iDatabase, KInsertNamesStmnt())); + index = stmt.ParameterIndex(KTzNamesTblTzIdParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindInt64(index, iNextCandidateTzId)); + index = stmt.ParameterIndex(KTzNamesTblStdNameParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindText(index, aNames.StandardName())); + index = stmt.ParameterIndex(KTzNamesTblShortStdNameParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindText(index, aNames.ShortStandardName())); + index = stmt.ParameterIndex(KTzNamesTblDSTNameParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindText(index, aNames.DaylightSaveName())); + index = stmt.ParameterIndex(KTzNamesTblShortDSTNameParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindText(index, aNames.ShortDaylightSaveName())); + index = stmt.ParameterIndex(KTzNamesTblCityNameParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindText(index, aNames.CityName())); + index = stmt.ParameterIndex(KTzNamesTblRegionNameParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindText(index, aNames.RegionName())); + TInt ret = stmt.Exec(); + stmt.Close(); + + if(ret < KErrNone) + { + User::Leave(ret); + } + + User::LeaveIfError(stmt.Prepare(iDatabase, KInsertInitialStdOffsetStmnt)); + index = stmt.ParameterIndex(KTzInitialStdOffsetTblTzIdParam); + User::LeaveIfError(index); + User::LeaveIfError(stmt.BindInt(index, iNextCandidateTzId)); + index = stmt.ParameterIndex(KTzInitialStdOffsetTblStdInitialOffsetParam); + User::LeaveIfError(index); + TInt initialOffset = aRules.InitialStdTimeOffset(); + User::LeaveIfError(stmt.BindInt(index, initialOffset)); + ret = stmt.Exec(); + stmt.Close(); + + if(ret < KErrNone) + { + User::Leave(ret); + } + + // Update the next available user ID + if(iNextCandidateTzId >= KUserTzIdMax) + { + iNextCandidateTzId = FindUnusedTzIdL(); + } + else + { + iNextCandidateTzId++; + } + + //Insert a row with the new available value of tz id in TZ IdentifierTable + User::LeaveIfError(stmt.Prepare(iDatabase, KUpdateIdentifierStmnt)); + User::LeaveIfError(stmt.BindInt64(0, iNextCandidateTzId)); + ret = stmt.Exec(); + stmt.Close(); + + if(ret < KErrNone) + { + User::Leave(ret); + } + + CommitTransactionL(); + NotifyTzRulesChange(retId, ETzUserDataCreated); + NotifyTzNamesChange(retId, ETzUserDataCreated); + + CleanupStack::PopAndDestroy(&stmt); + return retId; + } + +void CTzUserDataDb::ReadTzRulesL(CTzRules& aRules, TUint aTzId) + { + if(iBackupInProgress || iRestoreInProgress) + { + User::Leave(KErrLocked); + } + + TSqlScalarFullSelectQuery fullSelectQuery(iDatabase); + + RSqlStatement stmt; + CleanupClosePushL(stmt); + + TTzRule tzRule; + + TBuf sqlRules; + sqlRules.Format(KSelectRulesCountStmnt, aTzId); + TInt count = fullSelectQuery.SelectIntL(sqlRules); + if(count == 0) + { + User::Leave(KErrNotFound); + } + + sqlRules.Format(KSelectRulesStmnt, aTzId); + TInt err = stmt.Prepare(iDatabase, sqlRules); + User::LeaveIfError(err); + + TInt ruleTypeColIdx = stmt.ColumnIndex(KTzRulesTblRuleTypeIndex); + User::LeaveIfError(ruleTypeColIdx); + TInt startTimeColIdx = stmt.ColumnIndex(KTzRulesTblDSTStartTimeIndex); + User::LeaveIfError(startTimeColIdx); + TInt startRefColIdx = stmt.ColumnIndex(KTzRulesTblDSTStartRefIndex); + User::LeaveIfError(startRefColIdx); + TInt endTimeColIdx = stmt.ColumnIndex(KTzRulesTblDSTEndTimeIndex); + User::LeaveIfError(endTimeColIdx); + TInt endRefColIdx = stmt.ColumnIndex(KTzRulesTblDSTEndRefIndex); + User::LeaveIfError(endRefColIdx); + TInt oldOffsetColIdx = stmt.ColumnIndex(KTzRulesTblOldOffsetIndex); + User::LeaveIfError(oldOffsetColIdx); + TInt newOffsetColIdx = stmt.ColumnIndex(KTzRulesTblNewOffsetIndex); + User::LeaveIfError(newOffsetColIdx); + TInt monthColIdx = stmt.ColumnIndex(KTzRulesTblMonthIndex); + User::LeaveIfError(monthColIdx); + TInt dayColIdx = stmt.ColumnIndex(KTzRulesTblDayIndex); + User::LeaveIfError(dayColIdx); + TInt weekColIdx = stmt.ColumnIndex(KTzRulesTblWeekIndex); + User::LeaveIfError(weekColIdx); + TInt timeRefColIdx = stmt.ColumnIndex(KTzRulesTblTimeRefIndex); + User::LeaveIfError(timeRefColIdx); + TInt minsColIdx = stmt.ColumnIndex(KTzRulesTblMinsIndex); + User::LeaveIfError(minsColIdx); + + while((err = stmt.Next()) == KSqlAtRow) + { + tzRule.iDayRule = static_cast(stmt.ColumnInt(ruleTypeColIdx)); + + tzRule.iFrom.iTime = stmt.ColumnInt64(startTimeColIdx); + + tzRule.iFrom.iTimeReference = static_cast(stmt.ColumnInt(startRefColIdx)); + + tzRule.iTo.iTime = stmt.ColumnInt64(endTimeColIdx); + + tzRule.iTo.iTimeReference = static_cast(stmt.ColumnInt(endRefColIdx)); + + tzRule.iOldLocalTimeOffset = stmt.ColumnInt(oldOffsetColIdx); + + tzRule.iNewLocalTimeOffset = stmt.ColumnInt(newOffsetColIdx); + + tzRule.iMonth = static_cast(stmt.ColumnInt(monthColIdx)); + + tzRule.iDayOfMonth = stmt.ColumnInt(dayColIdx); + + tzRule.iDayOfWeek = stmt.ColumnInt(weekColIdx); + + tzRule.iTimeReference = static_cast(stmt.ColumnInt(timeRefColIdx)); + + tzRule.iTimeOfChange = stmt.ColumnInt(minsColIdx); + + aRules.AddRuleL(tzRule); + } + stmt.Close(); + + sqlRules.Format(KSelectInitialStdOffsetStmnt, aTzId); + err = stmt.Prepare(iDatabase, sqlRules); + User::LeaveIfError(err); + TInt stdInitialOffsetIdx = stmt.ColumnIndex(KTzInitialStdOffsetTblStdInitialOffsetIndex); + User::LeaveIfError(stdInitialOffsetIdx); + + // Fetch the row. + User::LeaveIfError(stmt.Next()); + + TInt stdInitialOffset = stmt.ColumnInt(stdInitialOffsetIdx); + aRules.SetInitialStdTimeOffset(stdInitialOffset); + + // This must be the only row. + __ASSERT_ALWAYS(stmt.Next() == KSqlAtEnd, RTz::Panic(RTz::EPanicBadSchema)); + + CleanupStack::PopAndDestroy(&stmt); + } + +CTzUserNames* CTzUserDataDb::ReadTzNamesL(TUint aTzId) + { + if(iBackupInProgress || iRestoreInProgress) + { + User::Leave(KErrLocked); + } + + RSqlStatement stmt; + CleanupClosePushL(stmt); + + TBuf sqlNames; + TSqlScalarFullSelectQuery fullSelectQuery(iDatabase); + sqlNames.Format(KSelectNamesCountStmnt, aTzId); + TInt count = fullSelectQuery.SelectIntL(sqlNames); + + if(count == 0) + { + User::Leave(KErrNotFound); + } + + sqlNames.Format(KSelectNamesStmnt, aTzId); + TInt err = stmt.Prepare(iDatabase, sqlNames); + User::LeaveIfError(err); + + TInt stdNameColIdx = stmt.ColumnIndex(KTzNamesTblStdNameIndex); + User::LeaveIfError(stdNameColIdx); + + TInt shortStdNameColIdx = stmt.ColumnIndex(KTzNamesTblShortStdNameIndex); + User::LeaveIfError(shortStdNameColIdx); + + TInt dstNameColIdx = stmt.ColumnIndex(KTzNamesTblDSTNameIndex); + User::LeaveIfError(dstNameColIdx); + + TInt shortDstNameColIdx = stmt.ColumnIndex(KTzNamesTblShortDSTNameIndex); + User::LeaveIfError(shortDstNameColIdx); + + TInt cityNameColIdx = stmt.ColumnIndex(KTzNamesTblCityNameIndex); + User::LeaveIfError(cityNameColIdx); + + TInt regionNameColIdx = stmt.ColumnIndex(KTzNamesTblRegionNameIndex); + User::LeaveIfError(regionNameColIdx); + + CTzUserNames* userNames = NULL; + + // Fetch the row. + User::LeaveIfError(stmt.Next()); + + TPtrC standardName; + standardName.Set(stmt.ColumnTextL(stdNameColIdx)); + + TPtrC shortStandardName; + shortStandardName.Set(stmt.ColumnTextL(shortStdNameColIdx)); + + TPtrC daylightName; + daylightName.Set(stmt.ColumnTextL(dstNameColIdx)); + + TPtrC shortDaylightName; + shortDaylightName.Set(stmt.ColumnTextL(shortDstNameColIdx)); + + TPtrC cityName; + cityName.Set(stmt.ColumnTextL(cityNameColIdx)); + + TPtrC regionName; + regionName.Set(stmt.ColumnTextL(regionNameColIdx)); + + userNames = CTzUserNames::NewL(standardName, shortStandardName, + daylightName, shortDaylightName, cityName, regionName); + + // This must be the only row. + __ASSERT_ALWAYS(stmt.Next() == KSqlAtEnd, RTz::Panic(RTz::EPanicBadSchema)); + + CleanupStack::PopAndDestroy(&stmt); + + return userNames; + } + +void CTzUserDataDb::ReadTzIdsL(RArray& aTzIds) + { + if(iBackupInProgress || iRestoreInProgress ) + { + User::Leave(KErrLocked); + } + + RSqlStatement stmt; + CleanupClosePushL(stmt); + + TBuf sqlRule; + sqlRule.Format(KSelectTzIdFromNamesStmnt); + TInt err = stmt.Prepare(iDatabase, sqlRule); + User::LeaveIfError(err); + + while((err = stmt.Next()) == KSqlAtRow) + { + TInt col = stmt.ColumnIndex(KTzNamesTblTzIdIndex); + User::LeaveIfError(col); + TUint id = stmt.ColumnInt64(col); + aTzIds.AppendL(id); + } + + CleanupStack::PopAndDestroy(&stmt); + } + +void CTzUserDataDb::UpdateTzL(TUint aTzId, const CTzRules& aTzRules, const CTzUserNames& aTzNames) + { + if(iBackupInProgress || iRestoreInProgress) + { + User::Leave(KErrLocked); + } + + RSqlStatement stmt; + CleanupClosePushL(stmt); + + BeginTransactionL(); + + TBuf sqlRules; + sqlRules.Format(KDeleteRulesStmnt, aTzId); + TInt ret = stmt.Prepare(iDatabase, sqlRules); + if(ret == KErrNone) + { + ret = stmt.Exec(); + if(ret < KErrNone) + { + User::Leave(ret); + } + } + stmt.Close(); + + const TInt count = aTzRules.Count(); + for(TInt i=0; i(aTzRules)[i]; + + User::LeaveIfError(stmt.Prepare(iDatabase, KInsertRulesStmnt)); + + TInt paramIdx = stmt.ParameterIndex(KTzRulesTblTzIdParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindInt64(paramIdx, aTzId)); + + paramIdx = stmt.ParameterIndex(KTzRulesTblRuleTypeParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindInt(paramIdx, rule.iDayRule)); + + paramIdx = stmt.ParameterIndex(KTzRulesTblDSTStartTimeParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindInt64(paramIdx, rule.iFrom.iTime.Int64())); + + paramIdx = stmt.ParameterIndex(KTzRulesTblDSTStartRefParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindInt(paramIdx, rule.iFrom.iTimeReference)); + + paramIdx = stmt.ParameterIndex(KTzRulesTblDSTEndTimeParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindInt64(paramIdx, rule.iTo.iTime.Int64())); + + paramIdx = stmt.ParameterIndex(KTzRulesTblDSTEndRefParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindInt(paramIdx, rule.iTo.iTimeReference)); + + paramIdx = stmt.ParameterIndex(KTzRulesTblOldOffsetParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindInt(paramIdx, rule.iOldLocalTimeOffset)); + + paramIdx = stmt.ParameterIndex(KTzRulesTblNewOffsetParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindInt(paramIdx, rule.iNewLocalTimeOffset)); + + paramIdx = stmt.ParameterIndex(KTzRulesTblMonthParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindInt(paramIdx, rule.iMonth)); + + paramIdx = stmt.ParameterIndex(KTzRulesTblDayParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindInt(paramIdx, rule.iDayOfMonth)); + + paramIdx = stmt.ParameterIndex(KTzRulesTblWeekParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindInt(paramIdx, rule.iDayOfWeek)); + + paramIdx = stmt.ParameterIndex(KTzRulesTblTimeRefParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindInt(paramIdx, rule.iTimeReference)); + + paramIdx = stmt.ParameterIndex(KTzRulesTblMinsParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindInt(paramIdx, rule.iTimeOfChange)); + + ret = stmt.Exec(); + stmt.Close(); + if(ret < KErrNone) + { + User::Leave(ret); + } + } + + TBuf sqlInitialOffset; + sqlInitialOffset.Format(KDeleteInitialStdOffset, aTzId); + ret = stmt.Prepare(iDatabase, sqlInitialOffset); + if(ret == KErrNone) + { + ret = stmt.Exec(); + stmt.Close(); + if(ret < KErrNone) + { + User::Leave(ret); + } + } + + User::LeaveIfError(stmt.Prepare(iDatabase, KInsertInitialStdOffsetStmnt)); + + TInt paramIdx = stmt.ParameterIndex(KTzInitialStdOffsetTblTzIdParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindInt64(paramIdx, aTzId)); + + TInt initialOffset = aTzRules.InitialStdTimeOffset(); + + paramIdx = stmt.ParameterIndex(KTzInitialStdOffsetTblStdInitialOffsetParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindInt64(paramIdx, initialOffset)); + + ret = stmt.Exec(); + stmt.Close(); + if(ret < KErrNone) + { + User::Leave(ret); + } + + TBuf sqlNames; + sqlNames.Format(KDeleteNamesStmnt, aTzId); + ret = stmt.Prepare(iDatabase, sqlNames); + if(ret == KErrNone) + { + ret = stmt.Exec(); + if(ret < KErrNone) + { + User::Leave(ret); + } + } + stmt.Close(); + + // Insert a row in the names + User::LeaveIfError(stmt.Prepare(iDatabase, KInsertNamesStmnt)); + + paramIdx = stmt.ParameterIndex(KTzNamesTblTzIdParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindInt64(paramIdx, aTzId)); + + paramIdx = stmt.ParameterIndex(KTzNamesTblStdNameParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindText(paramIdx, aTzNames.StandardName())); + + paramIdx = stmt.ParameterIndex(KTzNamesTblShortStdNameParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindText(paramIdx, aTzNames.ShortStandardName())); + + paramIdx = stmt.ParameterIndex(KTzNamesTblDSTNameParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindText(paramIdx, aTzNames.DaylightSaveName())); + + paramIdx = stmt.ParameterIndex(KTzNamesTblShortDSTNameParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindText(paramIdx, aTzNames.ShortDaylightSaveName())); + + paramIdx = stmt.ParameterIndex(KTzNamesTblCityNameParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindText(paramIdx, aTzNames.CityName())); + + paramIdx = stmt.ParameterIndex(KTzNamesTblRegionNameParam); + User::LeaveIfError(paramIdx); + User::LeaveIfError(stmt.BindText(paramIdx, aTzNames.RegionName())); + + ret = stmt.Exec(); + stmt.Close(); + if(ret < KErrNone) + { + User::Leave(ret); + } + + CommitTransactionL(); + + NotifyTzRulesChange(aTzId, ETzUserDataUpdated); + NotifyTzNamesChange(aTzId, ETzUserDataUpdated); + + CleanupStack::PopAndDestroy(&stmt); + } + +/** +Delete the time zone rule and name from the database that matches aTzId +*/ +void CTzUserDataDb::DeleteTzL(TUint aTzId) + { + if(iBackupInProgress || iRestoreInProgress) + { + User::Leave(KErrLocked); + } + + RSqlStatement stmt; + CleanupClosePushL(stmt); + + BeginTransactionL(); + + TInt ret; + TBuf sqlRules; + sqlRules.Format(KDeleteRulesStmnt, aTzId); + User::LeaveIfError(stmt.Prepare(iDatabase, sqlRules)); + ret = stmt.Exec(); + stmt.Close(); + if(ret < KErrNone) + { + User::Leave(ret); + } + + TBuf sqlInitialOffset; + sqlInitialOffset.Format(KDeleteInitialStdOffset, aTzId); + ret = stmt.Prepare(iDatabase, sqlInitialOffset); + if(ret == KErrNone) + { + ret = stmt.Exec(); + stmt.Close(); + if(ret < KErrNone) + { + User::Leave(ret); + } + } + + TBuf sqlNames; + sqlNames.Format(KDeleteNamesStmnt, aTzId); + User::LeaveIfError(stmt.Prepare(iDatabase, sqlNames)); + ret = stmt.Exec(); + stmt.Close(); + + if(ret < KErrNone) + { + User::Leave(ret); + } + + CommitTransactionL(); + + NotifyTzRulesChange(aTzId, ETzUserDataDeleted); + NotifyTzNamesChange(aTzId, ETzUserDataDeleted); + + CleanupStack::PopAndDestroy(&stmt); + } + +void CTzUserDataDb::CleanupDatabaseRollback(TAny *aDatabase) + { + ASSERT(aDatabase); + CTzUserDataDb* db = static_cast(aDatabase); + db->RollbackTransaction(); + } + +/** +Begin a new transation +*/ +void CTzUserDataDb::BeginTransactionL() + { + User::LeaveIfError(iDatabase.Exec(KBeginTransaction)); + CleanupStack::PushL(TCleanupItem(CleanupDatabaseRollback, this)); + } + +/** +Commit the changes made since the start of a transaction +*/ +void CTzUserDataDb::CommitTransactionL() + { + User::LeaveIfError(iDatabase.Exec(KCommitTransaction)); + CleanupStack::Pop(); //CleanupDatabaseRollback + } + +/** +Rollback changes since the start of the transaction +*/ +void CTzUserDataDb::RollbackTransaction() + { + iDatabase.Exec(KRollbackTransaction); + } + +// Notification operations. +void CTzUserDataDb::NotifyTzRulesChange(TUint aTzId, TTzUserDataChangeOp aChangeOp) + { + TTzUserDataChange change; + change.iTzId = aTzId; + change.iOperation = aChangeOp; + + TInt j = 0; + TInt jEnd = iChangeObservers.Count(); + while (j < jEnd) + { + iChangeObservers[j]->NotifyUserTzRulesChange(change); + ++j; + } + + //Publish ETzRulesChange property to the subscribed clients + NTzUpdate::TTzRulesChange rulesChange; + rulesChange.iUTCTimeOfRulesChange.UniversalTime(); + TPckgBuf bufRules(rulesChange); + RProperty::Set(NTzUpdate::KPropertyCategory, NTzUpdate::ETzRulesChange, bufRules); + } + +void CTzUserDataDb::NotifyTzNamesChange(TUint aTzId, TTzUserDataChangeOp aChangeOp) + { + TTzUserDataChange change; + change.iTzId = aTzId; + change.iOperation = aChangeOp; + + TInt j = 0; + TInt jEnd = iChangeObservers.Count(); + while (j < jEnd) + { + iChangeObservers[j]->NotifyUserTzNamesChange(change); + ++j; + } + + //Publish ETzNamesChange property to the subscribed clients + NTzUpdate::TTzNamesChange namesChange; + namesChange.iUTCTimeOfNamesChange.UniversalTime(); + TPckgBuf bufNames(namesChange); + RProperty::Set(NTzUpdate::KPropertyCategory, NTzUpdate::ETzNamesChange, bufNames); + } + + // Backup and restore operations +void CTzUserDataDb::BackupBeginningL() + { + Close(); + iBackupInProgress = ETrue; + } + +void CTzUserDataDb::BackupCompletedL() + { + OpenL(); + iBackupInProgress = EFalse; + } + +void CTzUserDataDb::RestoreBeginningL() + { + Close(); + iRestoreInProgress = ETrue; + } + +void CTzUserDataDb::RestoreCompletedL() + { + OpenL(); + iRestoreInProgress = EFalse; + } + +void CTzUserDataDb::AddObserverL(MTzUserDataChangeObserver* aChangeObs) + { + User::LeaveIfError(iChangeObservers.Append(aChangeObs)); + } + +void CTzUserDataDb::RemoveObserver(MTzUserDataChangeObserver* aChangeObs) + { + TInt j = 0; + TInt jEnd = iChangeObservers.Count(); + while (j < jEnd) + { + if (iChangeObservers[j] == aChangeObs) + { + iChangeObservers.Remove(j); + break; + } + ++j; + } + } +/** +Checks if aTzId exists in the user timezone database +*/ +TBool CTzUserDataDb::IsIdInDbL(TUint aTzId) + { + TBuf sqlNames; + TSqlScalarFullSelectQuery fullSelectQuery(iDatabase); + sqlNames.Format(KSelectTzIdCountFromNamesStmnt, aTzId); + + TInt count = fullSelectQuery.SelectIntL(sqlNames); + if(count == 0) + { + return EFalse; + } + return ETrue; + } +/** +Find the next unused id in the database. If all ids have been used +KOutOfBoundsUserId will be returned +*/ +TUint32 CTzUserDataDb::FindUnusedTzIdL() + { + RArray ids; + CleanupClosePushL(ids); + ReadTzIdsL(ids); + const TInt count = ids.Count(); + TUint foundId = KOutOfBoundsUserId; + if(count > 0) + { + ids.SortSigned(); + + for(TInt i=0; i