sl@0
|
1 |
// Copyright (c) 2005-2010 Nokia Corporation and/or its subsidiary(-ies).
|
sl@0
|
2 |
// All rights reserved.
|
sl@0
|
3 |
// This component and the accompanying materials are made available
|
sl@0
|
4 |
// under the terms of "Eclipse Public License v1.0"
|
sl@0
|
5 |
// which accompanies this distribution, and is available
|
sl@0
|
6 |
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
sl@0
|
7 |
//
|
sl@0
|
8 |
// Initial Contributors:
|
sl@0
|
9 |
// Nokia Corporation - initial contribution.
|
sl@0
|
10 |
//
|
sl@0
|
11 |
// Contributors:
|
sl@0
|
12 |
//
|
sl@0
|
13 |
// Description:
|
sl@0
|
14 |
//
|
sl@0
|
15 |
|
sl@0
|
16 |
#include "SqlSrvFileData.h" //TSqlSrvFileData
|
sl@0
|
17 |
#include "SqlSrvMain.h" //CSqlServer
|
sl@0
|
18 |
#include "SqlSrvAuthorizer.h" //MSqlPolicyInspector
|
sl@0
|
19 |
#include "SqlSrvDatabase.h"
|
sl@0
|
20 |
#include "SqlSrvStatement.h"
|
sl@0
|
21 |
#include "SqlUtil.h" //Panic codes, Sql2OsErrCode()
|
sl@0
|
22 |
#include "SqlSrvUtil.h" //Global server functions
|
sl@0
|
23 |
#include "SqlCompact.h"
|
sl@0
|
24 |
#include "SqlSrvResourceProfiler.h"
|
sl@0
|
25 |
#include "OstTraceDefinitions.h"
|
sl@0
|
26 |
#ifdef OST_TRACE_COMPILER_IN_USE
|
sl@0
|
27 |
#include "SqlSrvDatabaseTraces.h"
|
sl@0
|
28 |
#endif
|
sl@0
|
29 |
#include "SqlTraceDef.h"
|
sl@0
|
30 |
|
sl@0
|
31 |
//
|
sl@0
|
32 |
// The following macro disables the creation/loading of the settings table.
|
sl@0
|
33 |
// It is for internal testing purposes only!
|
sl@0
|
34 |
//
|
sl@0
|
35 |
// __SQL_DISABLE_SYMBIAN_SETTINGS_TABLE__
|
sl@0
|
36 |
//
|
sl@0
|
37 |
// This means that the database index will always be rebuilt when loaded by
|
sl@0
|
38 |
// by the server regardless of the current system collation/locale in use.
|
sl@0
|
39 |
// The benefit of enabling this macro is that a client can send PRAGMA
|
sl@0
|
40 |
// commands to the SQL server before any tables have been explicity created in
|
sl@0
|
41 |
// a NON-SECURE database (secure databases still automatically get a security
|
sl@0
|
42 |
// policy table).
|
sl@0
|
43 |
//
|
sl@0
|
44 |
// The macro is applied inside:
|
sl@0
|
45 |
// CSqlSrvDatabase::StoreSettingsL
|
sl@0
|
46 |
// CSqlSrvDatabase::ProcessSettingsL
|
sl@0
|
47 |
//
|
sl@0
|
48 |
// We should inform the user at compile-time if this macro has been enabled:
|
sl@0
|
49 |
#if defined(__SQL_DISABLE_SYMBIAN_SETTINGS_TABLE__)
|
sl@0
|
50 |
#pragma message(">>> WARNING: Use of SYMBIAN_SETTINGS table has been disabled <<<")
|
sl@0
|
51 |
#endif
|
sl@0
|
52 |
|
sl@0
|
53 |
|
sl@0
|
54 |
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
sl@0
|
55 |
///////////////////////////// Local const data ///////////////////////////////////////////////////////
|
sl@0
|
56 |
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
sl@0
|
57 |
|
sl@0
|
58 |
const char* KErrMsg1 = "Missing ESCAPE expression";
|
sl@0
|
59 |
const char* KErrMsg2 = "ESCAPE expression must be a single character";
|
sl@0
|
60 |
|
sl@0
|
61 |
////////////////////////////////////////////////////////
|
sl@0
|
62 |
//Attach/detach SQL statements (zero-terminated strings)
|
sl@0
|
63 |
_LIT(KAttachDb, "ATTACH DATABASE :FileName AS :DbName\x0");
|
sl@0
|
64 |
_LIT(KDetachDb, "DETACH DATABASE :DbName\x0");
|
sl@0
|
65 |
////////////////////////////////////////////////////////
|
sl@0
|
66 |
// Pragma SQL statements. The database names in all statements are quoted to avoid the "sql injection" threat.
|
sl@0
|
67 |
// (At the moment there is no way to pass an invalid database name for these statements, because the database has to be attached
|
sl@0
|
68 |
// first and a parameter binding is used there. So, the quoting is just for safety and against changes in the future)
|
sl@0
|
69 |
_LIT(KCacheSizePragma, "PRAGMA \"%S\".cache_size=%d\x0");
|
sl@0
|
70 |
_LIT(KPageSizePragma, "PRAGMA \"%S\".page_size=%d\x0");
|
sl@0
|
71 |
_LIT(KAutoVacuumPragma, "PRAGMA \"%S\".auto_vacuum=%d\x0");
|
sl@0
|
72 |
//_LIT(KPersist, "persist");
|
sl@0
|
73 |
//_LIT(KPersistentJournalPragma, "PRAGMA \"%S\".journal_mode=%S\x0");
|
sl@0
|
74 |
_LIT(KJournalSizeLimitPragma, "PRAGMA \"%S\".journal_size_limit=%d\x0");
|
sl@0
|
75 |
////////////////////////////////////////////////////////
|
sl@0
|
76 |
//"LIKE" - user defined function name
|
sl@0
|
77 |
_LIT8(KStrLikeFuncName, "LIKE\x0");
|
sl@0
|
78 |
|
sl@0
|
79 |
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
sl@0
|
80 |
///////////////////////////// Local functions ///////////////////////////////////////////////////////
|
sl@0
|
81 |
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
sl@0
|
82 |
|
sl@0
|
83 |
//Local function, used for comparing TSqlAttachDbPair objects.
|
sl@0
|
84 |
//(TSqlAttachDbPair structure represents type of the objects, members
|
sl@0
|
85 |
// of the map used for keeping the information regarding attached databases)
|
sl@0
|
86 |
//
|
sl@0
|
87 |
//Note that iKey members of aLeft and aRight function parameters are expected to be
|
sl@0
|
88 |
//UTF8 encoded, zero-terminated strings.
|
sl@0
|
89 |
//
|
sl@0
|
90 |
//The function will panic with panic code 7 in _DEBUG mode if iKey member of aLeft or
|
sl@0
|
91 |
//aRight argument is NULL.
|
sl@0
|
92 |
static TInt Compare(const TSqlAttachDbPair& aLeft, const TSqlAttachDbPair& aRight)
|
sl@0
|
93 |
{
|
sl@0
|
94 |
__ASSERT_DEBUG(aLeft.iKey != NULL && aRight.iKey != NULL, __SQLPANIC2(ESqlPanicInternalError));
|
sl@0
|
95 |
return ::CompareNoCase8(TPtrC8(aLeft.iKey), TPtrC8(aRight.iKey));
|
sl@0
|
96 |
}
|
sl@0
|
97 |
|
sl@0
|
98 |
//Local function, used for comparing TSqlCompactDbPair objects.
|
sl@0
|
99 |
//(TSqlCompactDbPair structure represents type of the objects, members
|
sl@0
|
100 |
// of the map used for keeping the information regarding compacted databases)
|
sl@0
|
101 |
//
|
sl@0
|
102 |
//Note that iKey members of aLeft and aRight function parameters are expected to be
|
sl@0
|
103 |
//UTF16 encoded strings.
|
sl@0
|
104 |
//
|
sl@0
|
105 |
//The function will panic with panic code 7 in _DEBUG mode if iKey member of aLeft or
|
sl@0
|
106 |
//aRight argument is NULL.
|
sl@0
|
107 |
static TInt Compare2(const TSqlCompactDbPair& aLeft, const TSqlCompactDbPair& aRight)
|
sl@0
|
108 |
{
|
sl@0
|
109 |
__ASSERT_DEBUG(aLeft.iKey != NULL && aRight.iKey != NULL, __SQLPANIC2(ESqlPanicInternalError));
|
sl@0
|
110 |
return ::CompareNoCase(*aLeft.iKey, *aRight.iKey);
|
sl@0
|
111 |
}
|
sl@0
|
112 |
|
sl@0
|
113 |
//Creates/opens database file (database file name in aFileData parameter) and initializes aDbHandle parameter.
|
sl@0
|
114 |
//The database will be created either with UTF-16 or UTF-8 encoding, depending on the
|
sl@0
|
115 |
//TSqlSrvFileData::IsUTF16() property.
|
sl@0
|
116 |
static void CreateDbHandleL(const TSqlSrvFileData& aFileData, sqlite3*& aDbHandle)
|
sl@0
|
117 |
{
|
sl@0
|
118 |
if(aFileData.ConfigParams().iDbEncoding == TSqlSrvConfigParams::EEncUtf8)
|
sl@0
|
119 |
{
|
sl@0
|
120 |
TBuf8<KMaxFileName + 1> fileNameZ;
|
sl@0
|
121 |
if(!::UTF16ZToUTF8Z(aFileData.FileNameZ(), fileNameZ))
|
sl@0
|
122 |
{
|
sl@0
|
123 |
__SQLLEAVE2(KErrGeneral);
|
sl@0
|
124 |
}
|
sl@0
|
125 |
__SQLLEAVE_IF_ERROR2(::CreateDbHandle8(fileNameZ, aDbHandle));
|
sl@0
|
126 |
}
|
sl@0
|
127 |
else
|
sl@0
|
128 |
{
|
sl@0
|
129 |
__SQLLEAVE_IF_ERROR2(::CreateDbHandle16(aFileData.FileNameZ(), aDbHandle));
|
sl@0
|
130 |
}
|
sl@0
|
131 |
}
|
sl@0
|
132 |
|
sl@0
|
133 |
//LoadAttachedDbSecurityPolicyLC() creates a new CSqlSecurityPolicy object and initializes it with the
|
sl@0
|
134 |
//security policies read from the attached database file, which name is in aFileData parameter.
|
sl@0
|
135 |
//The created database security policy object is placed in the cleanup stack.
|
sl@0
|
136 |
//The caller is responsible for the destruction of the created and returned security policy object.
|
sl@0
|
137 |
//This function is used to read the security policies of attached databases.
|
sl@0
|
138 |
static CSqlSecurityPolicy* LoadAttachedDbSecurityPolicyLC(const TSqlSrvFileData& aFileData)
|
sl@0
|
139 |
{
|
sl@0
|
140 |
//Create new database security policy object and initialize it with a default security policy
|
sl@0
|
141 |
TSecurityPolicy defaultPolicy(TSecurityPolicy::EAlwaysFail);
|
sl@0
|
142 |
CSqlSecurityPolicy* dbPolicy = CSqlSecurityPolicy::NewLC(defaultPolicy);
|
sl@0
|
143 |
//This is an attached database and has to be opened
|
sl@0
|
144 |
sqlite3* dbHandle = NULL;
|
sl@0
|
145 |
CreateDbHandleL(aFileData, dbHandle);
|
sl@0
|
146 |
CleanupStack::PushL(TCleanupItem(&CloseDbCleanup, dbHandle));
|
sl@0
|
147 |
//Read the security policies.
|
sl@0
|
148 |
TSqlDbSysSettings dbSysSettings(dbHandle);
|
sl@0
|
149 |
dbSysSettings.LoadSecurityPolicyL(*dbPolicy);
|
sl@0
|
150 |
CleanupStack::PopAndDestroy();//TCleanupItem(&CloseDbCleanup, dbHandle)
|
sl@0
|
151 |
return dbPolicy;
|
sl@0
|
152 |
}
|
sl@0
|
153 |
|
sl@0
|
154 |
//LoadDbSecurityPolicyLC() creates a new CSqlSecurityPolicy object and initializes it with the
|
sl@0
|
155 |
//security policies read from the database file.
|
sl@0
|
156 |
//The created database security policy object is placed in the cleanup stack.
|
sl@0
|
157 |
//The caller is responsible for destroying the returned database security policy object.
|
sl@0
|
158 |
//The function is used to read the security policy of the main database.
|
sl@0
|
159 |
static CSqlSecurityPolicy* LoadDbSecurityPolicyLC(sqlite3* aDbHandle)
|
sl@0
|
160 |
{
|
sl@0
|
161 |
__ASSERT_DEBUG(aDbHandle != NULL, __SQLPANIC2(ESqlPanicBadArgument));
|
sl@0
|
162 |
//Create new database security policy object and initialize it with a default security policy
|
sl@0
|
163 |
TSecurityPolicy defaultPolicy(TSecurityPolicy::EAlwaysFail);
|
sl@0
|
164 |
CSqlSecurityPolicy* dbPolicy = CSqlSecurityPolicy::NewLC(defaultPolicy);
|
sl@0
|
165 |
//Read the security policies.
|
sl@0
|
166 |
TSqlDbSysSettings dbSysSettings(aDbHandle);
|
sl@0
|
167 |
dbSysSettings.LoadSecurityPolicyL(*dbPolicy);
|
sl@0
|
168 |
return dbPolicy;
|
sl@0
|
169 |
}
|
sl@0
|
170 |
|
sl@0
|
171 |
//CreateStrCopyLC() makes a copy of aSrc string and places it in the cleanup stack.
|
sl@0
|
172 |
//aSrc is expected to be UTF8 encoded, zero terminated string.
|
sl@0
|
173 |
//The function panics in _DEBUG mode if aSrc is NULL.
|
sl@0
|
174 |
static TUint8* CreateStrCopyLC(const TUint8* aSrc)
|
sl@0
|
175 |
{
|
sl@0
|
176 |
__ASSERT_DEBUG(aSrc != NULL, __SQLPANIC2(ESqlPanicBadArgument));
|
sl@0
|
177 |
TInt len = User::StringLength(aSrc) + 1;
|
sl@0
|
178 |
TUint8* copy = new (ELeave) TUint8[len];
|
sl@0
|
179 |
Mem::Copy(copy, aSrc, len);
|
sl@0
|
180 |
CleanupStack::PushL(copy);
|
sl@0
|
181 |
return copy;
|
sl@0
|
182 |
}
|
sl@0
|
183 |
|
sl@0
|
184 |
//EnableAuthorizer() function is used to reenable the authorizer callback
|
sl@0
|
185 |
//during the stack cleanup.
|
sl@0
|
186 |
static void EnableAuthorizer(void* aAuthorizerDisabled)
|
sl@0
|
187 |
{
|
sl@0
|
188 |
__ASSERT_DEBUG(aAuthorizerDisabled != NULL, __SQLPANIC2(ESqlPanicBadArgument));
|
sl@0
|
189 |
TBool* authorizerDisabled = static_cast <TBool*> (aAuthorizerDisabled);
|
sl@0
|
190 |
*authorizerDisabled = EFalse;
|
sl@0
|
191 |
}
|
sl@0
|
192 |
|
sl@0
|
193 |
//Used by DbFileCleanup()
|
sl@0
|
194 |
NONSHARABLE_STRUCT(TDbFileCleanup)
|
sl@0
|
195 |
{
|
sl@0
|
196 |
TDbFileCleanup(const TSqlSrvFileData& aSqlSrvFileData, sqlite3*& aDbHandle) :
|
sl@0
|
197 |
iSqlSrvFileData(aSqlSrvFileData),
|
sl@0
|
198 |
iDbHandle(aDbHandle)
|
sl@0
|
199 |
{
|
sl@0
|
200 |
//aDbHandle can be NULL (it is a reference to a pointer and the pointer can be initialized later)
|
sl@0
|
201 |
}
|
sl@0
|
202 |
void Cleanup()
|
sl@0
|
203 |
{
|
sl@0
|
204 |
::CloseDbHandle(iDbHandle);//This operation also deletes the journal file
|
sl@0
|
205 |
iDbHandle = NULL;
|
sl@0
|
206 |
(void)iSqlSrvFileData.Fs().Delete(iSqlSrvFileData.FileName());
|
sl@0
|
207 |
}
|
sl@0
|
208 |
private:
|
sl@0
|
209 |
const TSqlSrvFileData& iSqlSrvFileData;
|
sl@0
|
210 |
sqlite3*& iDbHandle;
|
sl@0
|
211 |
};
|
sl@0
|
212 |
|
sl@0
|
213 |
//DbFileCleanup() is used to close and delete the database file during the stack cleanup, if
|
sl@0
|
214 |
//CSqlSrvDatabase's ConstructL() method(s) leave (when creating a new database file).
|
sl@0
|
215 |
static void DbFileCleanup(void* aDbFileCleanup)
|
sl@0
|
216 |
{
|
sl@0
|
217 |
__ASSERT_DEBUG(aDbFileCleanup != NULL, __SQLPANIC2(ESqlPanicBadArgument));
|
sl@0
|
218 |
TDbFileCleanup* dbFileCleanup = static_cast <TDbFileCleanup*> (aDbFileCleanup);
|
sl@0
|
219 |
dbFileCleanup->Cleanup();
|
sl@0
|
220 |
}
|
sl@0
|
221 |
|
sl@0
|
222 |
//Executes "PRAGMA" SQL statement + INTEGER value.
|
sl@0
|
223 |
//Pragma parameters:
|
sl@0
|
224 |
// aValue - integer pragma value to be set;
|
sl@0
|
225 |
// aPragma - pragma statement, the format is: ""PRAGMA <database name>.<parameter name>=%d\x0""
|
sl@0
|
226 |
// aDbName - "main" or the attached database name
|
sl@0
|
227 |
//This function is used for setting "cache_size", "page_size", "auto_vacuum" pragmas.
|
sl@0
|
228 |
//During the call the authorizer will be disabled.
|
sl@0
|
229 |
static TInt ExecPragma(sqlite3* aDbHandle, TBool& aAuthorizerDisabled, const TDesC& aPragma, TInt aValue, const TDesC& aDbName = KMainDb16)
|
sl@0
|
230 |
{
|
sl@0
|
231 |
__SQLTRACE_INTERNALSEXPR(TPtrC pragmaprnptr(aPragma.Left(aPragma.Length() - 1)));
|
sl@0
|
232 |
SQL_TRACE_INTERNALS(OstTraceExt4(TRACE_INTERNALS, EXECPRAGMA_ENTRY, "Entry;0;ExecPragma;sqlite3*=0x%X;aPragma=%S;aValue=%d;aDbName=%S", (TUint)aDbHandle, __SQLPRNSTR(pragmaprnptr), aValue, __SQLPRNSTR(aDbName)));
|
sl@0
|
233 |
__ASSERT_DEBUG(aDbHandle != NULL, __SQLPANIC2(ESqlPanicBadArgument));
|
sl@0
|
234 |
TBuf<KMaxFileName + 64> pragmaSql;//(KMaxFileName + 64) characters buffer length is enough for the longest possible PRAGMA statement
|
sl@0
|
235 |
pragmaSql.Format(aPragma, &aDbName, aValue);
|
sl@0
|
236 |
TBool authorizerDisabledState = aAuthorizerDisabled;
|
sl@0
|
237 |
aAuthorizerDisabled = ETrue;
|
sl@0
|
238 |
TInt err = DbExecStmt16(aDbHandle, pragmaSql);
|
sl@0
|
239 |
aAuthorizerDisabled = authorizerDisabledState;
|
sl@0
|
240 |
SQL_TRACE_INTERNALS(OstTraceExt2(TRACE_INTERNALS, EXECPRAGMA_EXIT, "Exit;0;ExecPragma;sqlite3*=0x%X;err=%d", (TUint)aDbHandle, err));
|
sl@0
|
241 |
return err;
|
sl@0
|
242 |
}
|
sl@0
|
243 |
|
sl@0
|
244 |
//The journal size limit is set to be at lest 16 pages and no less than 64 Kb.
|
sl@0
|
245 |
static void SetJournalSizeLimitL(sqlite3* aDbHandle, TBool& aAuthorizerDisabled, TInt aPageSize, const TDesC& aDbName = KMainDb16)
|
sl@0
|
246 |
{
|
sl@0
|
247 |
__ASSERT_DEBUG(aDbHandle != NULL, __SQLPANIC2(ESqlPanicBadArgument));
|
sl@0
|
248 |
if(aPageSize == TSqlSrvConfigParams::KConfigPrmValueNotSet)
|
sl@0
|
249 |
{
|
sl@0
|
250 |
__SQLLEAVE_IF_ERROR2(DbPageSize(aDbHandle, aDbName, aPageSize));
|
sl@0
|
251 |
}
|
sl@0
|
252 |
const TInt KPageMultiplier = 16;
|
sl@0
|
253 |
const TInt KDefaultJournalSizeLimit = 64 * 1024;
|
sl@0
|
254 |
const TInt KMaxJournalSizeLimit = 512 * 1024;
|
sl@0
|
255 |
const TInt KJournalSizeLimit = Min((aPageSize * KPageMultiplier), KMaxJournalSizeLimit);
|
sl@0
|
256 |
if(KJournalSizeLimit > KDefaultJournalSizeLimit)
|
sl@0
|
257 |
{
|
sl@0
|
258 |
__SQLLEAVE_IF_ERROR2(::ExecPragma(aDbHandle, aAuthorizerDisabled, KJournalSizeLimitPragma, KJournalSizeLimit));
|
sl@0
|
259 |
}
|
sl@0
|
260 |
}
|
sl@0
|
261 |
|
sl@0
|
262 |
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
sl@0
|
263 |
///////////////////////////// CSqlSrvDatabase class /////////////////////////////////////////////
|
sl@0
|
264 |
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
sl@0
|
265 |
|
sl@0
|
266 |
|
sl@0
|
267 |
|
sl@0
|
268 |
///////////////////////////// Object creation methods /////////////////////////////////////////////
|
sl@0
|
269 |
|
sl@0
|
270 |
/**
|
sl@0
|
271 |
Creates new CSqlSrvDatabase instance which creates and manages new secure SQL database.
|
sl@0
|
272 |
|
sl@0
|
273 |
@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
|
sl@0
|
274 |
file session reference and some other database file related properties.
|
sl@0
|
275 |
The format of the name must be:
|
sl@0
|
276 |
\<drive\>:\<[SID]database file name excluding the path\>.
|
sl@0
|
277 |
"[SID]" refers to SID of the application which creates the database.
|
sl@0
|
278 |
@param aSecurityPolicy The database security policies container.
|
sl@0
|
279 |
CSqlSrvDatabase instance stores the pointer in the security policy map,
|
sl@0
|
280 |
if it does not exist there already. The security policies map is owned by the CSqlServer class.
|
sl@0
|
281 |
|
sl@0
|
282 |
@return A pointer to the created CSqlSrvDatabase instance.
|
sl@0
|
283 |
|
sl@0
|
284 |
@see CSqlServer
|
sl@0
|
285 |
@see TSqlSrvFileData
|
sl@0
|
286 |
@see MSqlPolicyInspector
|
sl@0
|
287 |
@see RSqlSecurityMap
|
sl@0
|
288 |
@see CSqlSecurityPolicy
|
sl@0
|
289 |
|
sl@0
|
290 |
@leave KErrNoMemory, an out of memory condition has occurred;
|
sl@0
|
291 |
KErrArgument, if a system table name found in the security policies (aSecurityPolicy);
|
sl@0
|
292 |
KErrAlreadyExists, the file already exists;
|
sl@0
|
293 |
KErrNotReady, the drive does not exist or is not ready;
|
sl@0
|
294 |
KErrInUse, the file is already open;
|
sl@0
|
295 |
KErrPermissionDenied, the client application does not satisfy the relevant database security policies.
|
sl@0
|
296 |
Note that the function may also leave with some other database specific
|
sl@0
|
297 |
errors categorised as ESqlDbError, and other system-wide error codes.
|
sl@0
|
298 |
|
sl@0
|
299 |
@panic SqlDb 4 In _DEBUG mode if aFileData does not refer to a secure database file name.
|
sl@0
|
300 |
@panic SqlDb 4 In _DEBUG mode if aSecurityPolicy is NULL.
|
sl@0
|
301 |
*/
|
sl@0
|
302 |
CSqlSrvDatabase* CSqlSrvDatabase::CreateSecureL(const TSqlSrvFileData& aFileData, CSqlSecurityPolicy* aSecurityPolicy)
|
sl@0
|
303 |
{
|
sl@0
|
304 |
SQL_TRACE_INTERNALS(OstTrace0(TRACE_INTERNALS, CSQLSRVDATABASE_CREATESECUREL_ENTRY, "Entry;0;CSqlSrvDatabase::CreateSecureL"));
|
sl@0
|
305 |
__ASSERT_DEBUG(aFileData.IsSecureFileNameFmt(), __SQLPANIC2(ESqlPanicBadArgument));
|
sl@0
|
306 |
__ASSERT_DEBUG(aSecurityPolicy != NULL, __SQLPANIC2(ESqlPanicBadArgument));
|
sl@0
|
307 |
if(!::SqlServer().SecurityInspector().Check(aSecurityPolicy->DbPolicy(RSqlSecurityPolicy::ESchemaPolicy)))
|
sl@0
|
308 |
{
|
sl@0
|
309 |
//The caller has no "SCHEMA" policy. Then the client is not given a permission to create the database.
|
sl@0
|
310 |
//Delete aSecurityPolicy since no database object is going to be created and the security policy object
|
sl@0
|
311 |
//won't be put in the security policies map.
|
sl@0
|
312 |
delete aSecurityPolicy;
|
sl@0
|
313 |
__SQLLEAVE2(KErrPermissionDenied);
|
sl@0
|
314 |
}
|
sl@0
|
315 |
//What does happen with aSecurityPolicy instance?
|
sl@0
|
316 |
// If the database is created successfully, then a lookup will be made in the security policies map.
|
sl@0
|
317 |
// (the security policies map contains reference counted security policies)
|
sl@0
|
318 |
// If the same security policy already exists in the map, then aSecurityPolicy will be deleted.
|
sl@0
|
319 |
// The reference counter of the found policy will be incremented.
|
sl@0
|
320 |
// If aSecurityPolicy is not in the map, then it will be put in the map and removed
|
sl@0
|
321 |
// from the map when CSqlSrvDatabase object is destroyed.
|
sl@0
|
322 |
// (the "remove" operation decrements the security policy counter
|
sl@0
|
323 |
// and destroys the policy if it reaches 0)
|
sl@0
|
324 |
//
|
sl@0
|
325 |
//The security policy map pair is:
|
sl@0
|
326 |
//{secure_db_name, reference_counted db_security_policy}
|
sl@0
|
327 |
//The security policy is reference counted, because the same database can be shared between one or more
|
sl@0
|
328 |
//connections (clients), in which case only a single, reference counted instance of the database security
|
sl@0
|
329 |
//policy is kept in the map.
|
sl@0
|
330 |
CleanupStack::PushL(aSecurityPolicy);
|
sl@0
|
331 |
CSqlSrvDatabase* self = new (ELeave) CSqlSrvDatabase();
|
sl@0
|
332 |
CleanupStack::Pop(aSecurityPolicy);
|
sl@0
|
333 |
CleanupStack::PushL(self);
|
sl@0
|
334 |
self->ConstructCreateSecureL(aFileData, aSecurityPolicy);
|
sl@0
|
335 |
CleanupStack::Pop(self);
|
sl@0
|
336 |
SQL_TRACE_INTERNALS(OstTraceExt2(TRACE_INTERNALS, CSQLSRVDATABASE_CREATESECUREL_EXIT, "Exit;0x%X;CSqlSrvDatabase::CreateSecureL;sqlite3*=0x%X", (TUint)self, (TUint)self->iDbHandle));
|
sl@0
|
337 |
return self;
|
sl@0
|
338 |
}
|
sl@0
|
339 |
|
sl@0
|
340 |
/**
|
sl@0
|
341 |
Creates new CSqlSrvDatabase instance which creates and manages new SQL database.
|
sl@0
|
342 |
|
sl@0
|
343 |
@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
|
sl@0
|
344 |
file session reference and some other database file related properties.
|
sl@0
|
345 |
|
sl@0
|
346 |
@return A pointer to the created CSqlSrvDatabase instance.
|
sl@0
|
347 |
|
sl@0
|
348 |
@see CSqlServer
|
sl@0
|
349 |
@see TSqlSrvFileData
|
sl@0
|
350 |
@see MSqlPolicyInspector
|
sl@0
|
351 |
@see RSqlSecurityMap
|
sl@0
|
352 |
@see CSqlSecurityPolicy
|
sl@0
|
353 |
|
sl@0
|
354 |
@leave KErrNoMemory, an out of memory condition has occurred;
|
sl@0
|
355 |
KErrArgument, the file name is a name of a secure database;
|
sl@0
|
356 |
KErrAlreadyExists, the file already exists;
|
sl@0
|
357 |
KErrNotReady, the drive does not exist or is not ready;
|
sl@0
|
358 |
KErrInUse, the file is already open;
|
sl@0
|
359 |
KErrArgument, the file name refers to a secure database, but aSecurityPolicy is NULL;
|
sl@0
|
360 |
Note that the function may also leave with some other database specific
|
sl@0
|
361 |
errors categorised as ESqlDbError, and other system-wide error codes.
|
sl@0
|
362 |
|
sl@0
|
363 |
@panic SqlDb 4 In _DEBUG mode if aFileData refers to a secure database file name.
|
sl@0
|
364 |
*/
|
sl@0
|
365 |
CSqlSrvDatabase* CSqlSrvDatabase::CreateL(const TSqlSrvFileData& aFileData)
|
sl@0
|
366 |
{
|
sl@0
|
367 |
SQL_TRACE_INTERNALS(OstTrace0(TRACE_INTERNALS, CSQLSRVDATABASE_CREATEL_ENTRY, "Entry;0;CSqlSrvDatabase::CreateL"));
|
sl@0
|
368 |
__ASSERT_DEBUG(!aFileData.IsSecureFileNameFmt(), __SQLPANIC2(ESqlPanicBadArgument));
|
sl@0
|
369 |
CSqlSrvDatabase* self = new (ELeave) CSqlSrvDatabase();
|
sl@0
|
370 |
CleanupStack::PushL(self);
|
sl@0
|
371 |
self->ConstructCreateL(aFileData);
|
sl@0
|
372 |
CleanupStack::Pop(self);
|
sl@0
|
373 |
SQL_TRACE_INTERNALS(OstTraceExt2(TRACE_INTERNALS, CSQLSRVDATABASE_CREATEL_EXIT, "Exit;0x%X;CSqlSrvDatabase::CreateL;sqlite3*=0x%X", (TUint)self, (TUint)self->iDbHandle));
|
sl@0
|
374 |
return self;
|
sl@0
|
375 |
}
|
sl@0
|
376 |
|
sl@0
|
377 |
/**
|
sl@0
|
378 |
Creates new CSqlSrvDatabase instance which opens and manages an existing SQL database.
|
sl@0
|
379 |
|
sl@0
|
380 |
@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
|
sl@0
|
381 |
file session reference and some other database file related properties.
|
sl@0
|
382 |
If this is a secure database, then the format of the name must be:
|
sl@0
|
383 |
\<drive\>:\<[SID]database file name excluding the path\>.
|
sl@0
|
384 |
If this is a non-secure database, then the file name has to be the full database file name.
|
sl@0
|
385 |
"[SID]" refers to SID of the application which created the database.
|
sl@0
|
386 |
If this is application's private database, then the format of aFileData is as it is described
|
sl@0
|
387 |
in TSqlSrvFileData::SetFromHandleL() comments.
|
sl@0
|
388 |
|
sl@0
|
389 |
@return A pointer to the created CSqlSrvDatabase instance.
|
sl@0
|
390 |
|
sl@0
|
391 |
@leave KErrNoMemory, an out of memory condition has occurred;
|
sl@0
|
392 |
KErrNotReady, the drive does not exist or is not ready;
|
sl@0
|
393 |
KErrNotFound, the database file does not exist;
|
sl@0
|
394 |
KErrInUse, the file is already open;
|
sl@0
|
395 |
KErrPermissionDenied, the client application does not satisfy the relevant database security policies.
|
sl@0
|
396 |
Note that the function may also leave with some other database specific
|
sl@0
|
397 |
errors categorised as ESqlDbError, and other system-wide error codes.
|
sl@0
|
398 |
|
sl@0
|
399 |
@see CSqlServer
|
sl@0
|
400 |
@see TSqlSrvFileData
|
sl@0
|
401 |
@see MSqlPolicyInspector
|
sl@0
|
402 |
@see RSqlSecurityMap
|
sl@0
|
403 |
@see CSqlSecurityPolicy
|
sl@0
|
404 |
@see TSqlSrvFileData::SetFromHandleL()
|
sl@0
|
405 |
*/
|
sl@0
|
406 |
CSqlSrvDatabase* CSqlSrvDatabase::OpenL(const TSqlSrvFileData& aFileData)
|
sl@0
|
407 |
{
|
sl@0
|
408 |
SQL_TRACE_INTERNALS(OstTrace0(TRACE_INTERNALS, CSQLSRVDATABASE_OPENL_ENTRY, "Entry;0;CSqlSrvDatabase::OpenL"));
|
sl@0
|
409 |
CSqlSrvDatabase* self = new (ELeave) CSqlSrvDatabase();
|
sl@0
|
410 |
CleanupStack::PushL(self);
|
sl@0
|
411 |
aFileData.IsSecureFileNameFmt() ? self->ConstructOpenSecureL(aFileData) : self->ConstructOpenL(aFileData);
|
sl@0
|
412 |
CleanupStack::Pop(self);
|
sl@0
|
413 |
SQL_TRACE_INTERNALS(OstTraceExt2(TRACE_INTERNALS, CSQLSRVDATABASE_OPENL_EXIT, "Exit;0x%X;CSqlSrvDatabase::OpenL;sqlite3*=0x%X", (TUint)self, (TUint)self->iDbHandle));
|
sl@0
|
414 |
return self;
|
sl@0
|
415 |
}
|
sl@0
|
416 |
|
sl@0
|
417 |
/**
|
sl@0
|
418 |
Cleans up the allocated for the database connection memory and other resources.
|
sl@0
|
419 |
*/
|
sl@0
|
420 |
CSqlSrvDatabase::~CSqlSrvDatabase()
|
sl@0
|
421 |
{
|
sl@0
|
422 |
SQL_TRACE_INTERNALS(OstTraceExt2(TRACE_INTERNALS, CSQLSRVDATABASE_CSQLSRVDATABASE2_ENTRY, "Entry;0x%X;CSqlSrvDatabase::~CSqlSrvDatabase;sqlite3*=0x%X", (TUint)this, (TUint)iDbHandle));
|
sl@0
|
423 |
TSqlCompactDbMapIterator compactDbIt(iCompactDbMap);
|
sl@0
|
424 |
TSqlCompactDbPair compactDbPair;
|
sl@0
|
425 |
while(compactDbIt.Next(compactDbPair))
|
sl@0
|
426 |
{
|
sl@0
|
427 |
__ASSERT_DEBUG(compactDbPair.iData, __SQLPANIC2(ESqlPanicInvalidObj));
|
sl@0
|
428 |
::SqlServer().Compactor().ReleaseEntry(*compactDbPair.iData);
|
sl@0
|
429 |
}
|
sl@0
|
430 |
iCompactDbMap.Close();
|
sl@0
|
431 |
//If iSecureDbName is not NULL, the current CSqlSrvDatabase object operates on a secure database.
|
sl@0
|
432 |
//The database security policy has to be removed from the security policy map.
|
sl@0
|
433 |
//(The "remove" operation actually decrements the security policy reference counter and destroys the policy
|
sl@0
|
434 |
//when the counter reaches 0. The counter value may be greater than 1 if the database is shared between
|
sl@0
|
435 |
//more than one connection)
|
sl@0
|
436 |
if(iSecureDbName)
|
sl@0
|
437 |
{
|
sl@0
|
438 |
::SqlServer().SecurityMap().Remove(iSecureDbName);
|
sl@0
|
439 |
//The security policy map owns iSecureDbName and iSecurityPolicy and is responsible for
|
sl@0
|
440 |
//iSecureDbName and iSecurityPolicy destruction.
|
sl@0
|
441 |
}
|
sl@0
|
442 |
//The next step of the "resource release" process is to walk over iAttachDbMap entries, get the data part of
|
sl@0
|
443 |
//the found TSqlAttachDbPair objects, which is secure database name used as a key in iSecurityMap, and remove
|
sl@0
|
444 |
//the related entry from iSecurityMap. If the database is closed in normal circumstances, the iAttachDbMap
|
sl@0
|
445 |
//has no entries. But if the database client forgets to detach the used attached databases or if the Detach() call
|
sl@0
|
446 |
//fails (for example, with KErrNoMemory error), then at this point iAttachDbMap has one or more entries.
|
sl@0
|
447 |
//That means there are still some attached databases to this connection. This is not a problem, SQLite will take
|
sl@0
|
448 |
//care of them. The problem is that there are related entries in iSecurityMap map, owned by CSqlServer object,
|
sl@0
|
449 |
//and they won't be removed from the map till CSqlServer object is alive. This causes problems in OOM tests and in
|
sl@0
|
450 |
//real life of the device.
|
sl@0
|
451 |
//For example, one database client opens "c:[11111111]a.db" and attaches "c:[11111111]b.db":
|
sl@0
|
452 |
// - c:[11111111]a.db database has been opened successfully. iSecurityMap has 1 entry:
|
sl@0
|
453 |
// {"c:[11111111]a.db", <database security policy object>}.
|
sl@0
|
454 |
// - c:[11111111]b.db is attached to c:[11111111]a.db with name "db2". There will be 1 entry in iAttachDbMap:
|
sl@0
|
455 |
// {"db2", "c:[11111111]a.db"}
|
sl@0
|
456 |
// and a new entry will be added to iSecurityMap:
|
sl@0
|
457 |
// {"c:[11111111]b.db", <database security policy object>}. 2 entries in total in iSecurityMap.
|
sl@0
|
458 |
// - The database client attempts to detach the attached database but the opertaion fails during the execution
|
sl@0
|
459 |
// of the DETACH sql statement. Both maps are intact.
|
sl@0
|
460 |
// - The database client attempts to close the database. The previous implementation of CSqlSrvDatabase::~CSqlSrvDatabase()
|
sl@0
|
461 |
// would only remove "c:[11111111]a.db" entry from iSecurityMap and close the iAttachDbMap map.
|
sl@0
|
462 |
// The result: no opened or attached databases but there will be one entry in iSecurityMap: "c:[11111111]b.db".
|
sl@0
|
463 |
// OOM tests will report a memory leak in this case. On a real device, if "c:[11111111]b.db" gets deleted and
|
sl@0
|
464 |
// recreated again, unexpected memory leak will occur in CSqlSrvDatabase::ConstructCreateSecureL() because
|
sl@0
|
465 |
// the code there "expects" that is the first time when a "c:[11111111]b.db" entry is added to iSecurityMap.
|
sl@0
|
466 |
TSqlAttachDbMapIterator it(iAttachDbMap);
|
sl@0
|
467 |
TSqlAttachDbPair attachDbPair;
|
sl@0
|
468 |
while(it.Next(attachDbPair))
|
sl@0
|
469 |
{
|
sl@0
|
470 |
__ASSERT_DEBUG(attachDbPair.iData, __SQLPANIC2(ESqlPanicInvalidObj));
|
sl@0
|
471 |
::SqlServer().SecurityMap().Remove(attachDbPair.iData);
|
sl@0
|
472 |
}
|
sl@0
|
473 |
iAttachDbMap.Close();
|
sl@0
|
474 |
::CloseDbHandle(iDbHandle);
|
sl@0
|
475 |
SQL_TRACE_INTERNALS(OstTrace1(TRACE_INTERNALS, CSQLSRVDATABASE_CSQLSRVDATABASE2_EXIT, "Exit;0x%X;CSqlSrvDatabase::~CSqlSrvDatabase", (TUint)this));
|
sl@0
|
476 |
}
|
sl@0
|
477 |
|
sl@0
|
478 |
/**
|
sl@0
|
479 |
Initializes CSqlSrvDatabase data memebers with their default values.
|
sl@0
|
480 |
|
sl@0
|
481 |
|
sl@0
|
482 |
@see MSqlPolicyInspector
|
sl@0
|
483 |
@see RSqlSecurityMap
|
sl@0
|
484 |
@see CSqlServer
|
sl@0
|
485 |
*/
|
sl@0
|
486 |
CSqlSrvDatabase::CSqlSrvDatabase() :
|
sl@0
|
487 |
iAttachDbMap(TSqlAttachDbLinearOrder(&Compare), TSqlAttachDbDestructor()),
|
sl@0
|
488 |
iCompactDbMap(TSqlCompactDbLinearOrder(&Compare2), TSqlCompactDbDestructor())
|
sl@0
|
489 |
{
|
sl@0
|
490 |
}
|
sl@0
|
491 |
|
sl@0
|
492 |
/**
|
sl@0
|
493 |
Creates a new SQL database file and executes config pragmas.
|
sl@0
|
494 |
This function is part of CSqlSrvDatabase instance initialization.
|
sl@0
|
495 |
If the function leaves and the error is not KErrAlreadyExists, the database file will be deleted.
|
sl@0
|
496 |
|
sl@0
|
497 |
@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
|
sl@0
|
498 |
file session reference and some other database file related properties.
|
sl@0
|
499 |
If this is a secure database, then the format of the name must be:
|
sl@0
|
500 |
\<drive\>:\<[SID]database file name excluding the path\>.
|
sl@0
|
501 |
If this is a non-secure database, then the file name has to be the full database file name.
|
sl@0
|
502 |
"[SID]" refers to SID of the application which creates the database.
|
sl@0
|
503 |
|
sl@0
|
504 |
@see TSqlSrvFileData
|
sl@0
|
505 |
|
sl@0
|
506 |
@leave KErrNoMemory, an out of memory condition has occurred;
|
sl@0
|
507 |
KErrAlreadyExists, the file already exists.
|
sl@0
|
508 |
Note that the function may also leave with some other database specific
|
sl@0
|
509 |
errors categorised as ESqlDbError, and other system-wide error codes.
|
sl@0
|
510 |
*/
|
sl@0
|
511 |
void CSqlSrvDatabase::CreateNewDbFileL(const TSqlSrvFileData& aFileData)
|
sl@0
|
512 |
{
|
sl@0
|
513 |
__SQLTRACE_INTERNALSVAR(TPtrC fname = aFileData.FileName());
|
sl@0
|
514 |
SQL_TRACE_INTERNALS(OstTraceExt2(TRACE_INTERNALS, CSQLSRVDATABASE_CREATENEWDBFILEL, "0x%x;CSqlSrvDatabase::CreateNewDbFileL;fname=%S", (TUint)this, __SQLPRNSTR(fname)));
|
sl@0
|
515 |
if(::FileExists(aFileData.Fs(), aFileData.FileName()))
|
sl@0
|
516 |
{
|
sl@0
|
517 |
__SQLLEAVE(KErrAlreadyExists);
|
sl@0
|
518 |
}
|
sl@0
|
519 |
TDbFileCleanup dbFileCleanup(aFileData, iDbHandle);
|
sl@0
|
520 |
CleanupStack::PushL(TCleanupItem(&DbFileCleanup, &dbFileCleanup));
|
sl@0
|
521 |
::CreateDbHandleL(aFileData, iDbHandle);
|
sl@0
|
522 |
SetConfigL(aFileData.ConfigParams(), ETrue);
|
sl@0
|
523 |
CleanupStack::Pop();//DbFileCleanup
|
sl@0
|
524 |
}
|
sl@0
|
525 |
|
sl@0
|
526 |
/**
|
sl@0
|
527 |
Opens an existing SQL database file and executes config pragmas.
|
sl@0
|
528 |
|
sl@0
|
529 |
This function is part of CSqlSrvDatabase instance initialization.
|
sl@0
|
530 |
|
sl@0
|
531 |
@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
|
sl@0
|
532 |
file session reference and some other database file related properties.
|
sl@0
|
533 |
If this is a secure database, then the format of the name must be:
|
sl@0
|
534 |
\<drive\>:\<[SID]database file name excluding the path\>.
|
sl@0
|
535 |
If this is a non-secure database, then the file name has to be the full database file name.
|
sl@0
|
536 |
"[SID]" refers to SID of the application which creates the database.
|
sl@0
|
537 |
If this is application's private database, then the format of aFileData is as it is described
|
sl@0
|
538 |
in TSqlSrvFileData::SetFromHandleL() comments.
|
sl@0
|
539 |
|
sl@0
|
540 |
@leave KErrNoMemory, an out of memory condition has occurred;
|
sl@0
|
541 |
KErrNotFound, SQL database file not found.
|
sl@0
|
542 |
Note that the function may also leave with some other database specific
|
sl@0
|
543 |
errors categorised as ESqlDbError, and other system-wide error codes.
|
sl@0
|
544 |
|
sl@0
|
545 |
@see TSqlSrvFileData
|
sl@0
|
546 |
@see TSqlSrvFileData::SetFromHandleL()
|
sl@0
|
547 |
*/
|
sl@0
|
548 |
void CSqlSrvDatabase::OpenExistingDbFileL(const TSqlSrvFileData& aFileData)
|
sl@0
|
549 |
{
|
sl@0
|
550 |
__SQLTRACE_INTERNALSVAR(TPtrC fname = aFileData.FileName());
|
sl@0
|
551 |
SQL_TRACE_INTERNALS(OstTraceExt2(TRACE_INTERNALS, CSQLSRVDATABASE_OPENEXISTINGDBFILEL, "0x%x;CSqlSrvDatabase::OpenExistingDbFileL;fname=%S", (TUint)this, __SQLPRNSTR(fname)));
|
sl@0
|
552 |
if(!aFileData.ContainHandles())
|
sl@0
|
553 |
{//This check is valid only if the database is outside application's private data cage
|
sl@0
|
554 |
if(!::FileExists(aFileData.Fs(), aFileData.FileName()))
|
sl@0
|
555 |
{
|
sl@0
|
556 |
__SQLLEAVE(KErrNotFound);
|
sl@0
|
557 |
}
|
sl@0
|
558 |
}
|
sl@0
|
559 |
::CreateDbHandleL(aFileData, iDbHandle);
|
sl@0
|
560 |
//this is an existing database, only the cache size can be changed, the page size is persistent database property.
|
sl@0
|
561 |
//But for private databases, opened on the client side - the page size can be set (for the "create database" operations).
|
sl@0
|
562 |
SetConfigL(aFileData.ConfigParams(), aFileData.ContainHandles());
|
sl@0
|
563 |
}
|
sl@0
|
564 |
|
sl@0
|
565 |
/**
|
sl@0
|
566 |
Installs an authorizer callback function.
|
sl@0
|
567 |
|
sl@0
|
568 |
The callback function is invoked by the SQL parser at SQL statement compile time for each attempt
|
sl@0
|
569 |
to access a column of a table in the database and is used to assert the calling application's rights to
|
sl@0
|
570 |
perform specific SQL operation.
|
sl@0
|
571 |
|
sl@0
|
572 |
This function is part of CSqlSrvDatabase instance initialization.
|
sl@0
|
573 |
|
sl@0
|
574 |
@leave The function may leave with some database specific errors categorised as ESqlDbError.
|
sl@0
|
575 |
*/
|
sl@0
|
576 |
void CSqlSrvDatabase::InstallAuthorizerL()
|
sl@0
|
577 |
{
|
sl@0
|
578 |
//Install the authorizer just once. "Install authorizer" may be expensive and dangerous operation because
|
sl@0
|
579 |
//it will expire the already prepared statements.
|
sl@0
|
580 |
if(!iAuthorizerInstalled)
|
sl@0
|
581 |
{
|
sl@0
|
582 |
(void)sqlite3SymbianLastOsError();//clear last OS error
|
sl@0
|
583 |
TInt err = sqlite3_set_authorizer(iDbHandle, &CSqlSrvDatabase::AuthorizeCallback, this);
|
sl@0
|
584 |
__SQLLEAVE_IF_ERROR(::Sql2OsErrCode(err, sqlite3SymbianLastOsError()));
|
sl@0
|
585 |
}
|
sl@0
|
586 |
iAuthorizerInstalled = ETrue;
|
sl@0
|
587 |
}
|
sl@0
|
588 |
|
sl@0
|
589 |
#ifdef SYMBIAN_USE_SQLITE_VERSION_3_6_4
|
sl@0
|
590 |
extern "C" int sqlite3RegisterInternalUtf8Like(sqlite3 *db);
|
sl@0
|
591 |
#endif
|
sl@0
|
592 |
/**
|
sl@0
|
593 |
Installs user-defined functions. At the moment there is only one: LIKE.
|
sl@0
|
594 |
|
sl@0
|
595 |
Replacing the LIKE operator default implementation with user defined LIKE functions.
|
sl@0
|
596 |
The default implementation need a replacement because it does not work correctly with UTF16 encoded strings.
|
sl@0
|
597 |
*/
|
sl@0
|
598 |
void CSqlSrvDatabase::InstallUDFsL()
|
sl@0
|
599 |
{
|
sl@0
|
600 |
//Registering user defined LIKE function with 2 parameters for UTF16 encoding
|
sl@0
|
601 |
TInt err = sqlite3_create_function(iDbHandle, reinterpret_cast <const char*> (KStrLikeFuncName().Ptr()),
|
sl@0
|
602 |
2/*arg*/, SQLITE_UTF16, this /*user data*/,
|
sl@0
|
603 |
&CSqlSrvDatabase::LikeSqlFunc, NULL/*xStep*/, NULL/*xFinal*/);
|
sl@0
|
604 |
__SQLLEAVE_IF_ERROR(::Sql2OsErrCode(err, sqlite3SymbianLastOsError()));
|
sl@0
|
605 |
//Registering user defined LIKE function with 3 parameters for UTF16 encoding
|
sl@0
|
606 |
err = sqlite3_create_function(iDbHandle, reinterpret_cast <const char*> (KStrLikeFuncName().Ptr()),
|
sl@0
|
607 |
3/*arg*/, SQLITE_UTF16, this/*user data*/,
|
sl@0
|
608 |
&CSqlSrvDatabase::LikeSqlFunc, NULL/*xStep*/, NULL/*xFinal*/);
|
sl@0
|
609 |
__SQLLEAVE_IF_ERROR(::Sql2OsErrCode(err, sqlite3SymbianLastOsError()));
|
sl@0
|
610 |
|
sl@0
|
611 |
#ifdef SYMBIAN_USE_SQLITE_VERSION_3_6_4
|
sl@0
|
612 |
//Registering user defined LIKE function with 2 and 3 parameters for UTF8 encoding
|
sl@0
|
613 |
//Once registered, these will be treated as built-in functions
|
sl@0
|
614 |
err = sqlite3RegisterInternalUtf8Like(iDbHandle);
|
sl@0
|
615 |
__SQLLEAVE_IF_ERROR(::Sql2OsErrCode(err, sqlite3SymbianLastOsError()));
|
sl@0
|
616 |
#endif
|
sl@0
|
617 |
}
|
sl@0
|
618 |
|
sl@0
|
619 |
/**
|
sl@0
|
620 |
Constructs a key for searching in the security policies map.
|
sl@0
|
621 |
|
sl@0
|
622 |
The key is UTF8 encoded, zero-terminated string.
|
sl@0
|
623 |
|
sl@0
|
624 |
Every time when CSqlSrvDatabase instance creates, opens or attaches a secure database, it updates
|
sl@0
|
625 |
the contents of the security policies map (RSqlSecurityMap class), which is a single instance owned
|
sl@0
|
626 |
by the CSqlServer class.
|
sl@0
|
627 |
|
sl@0
|
628 |
@param aDbFileName Full secure database file name, from which the security policies map key
|
sl@0
|
629 |
will be constructed.
|
sl@0
|
630 |
|
sl@0
|
631 |
@return A const pointer to the constructed security map key. No memory is allocated for the key.
|
sl@0
|
632 |
|
sl@0
|
633 |
@leave KErrGeneral the UTF16 to UTF8 conversion of aDbFileName parameter failed.
|
sl@0
|
634 |
|
sl@0
|
635 |
@see RSqlSecurityMap
|
sl@0
|
636 |
@see CSqlServer
|
sl@0
|
637 |
*/
|
sl@0
|
638 |
const TUint8* CSqlSrvDatabase::SecurityMapKeyL(const TDesC& aDbFileName)
|
sl@0
|
639 |
{
|
sl@0
|
640 |
//Form the map item key - the secure database name
|
sl@0
|
641 |
TParsePtrC parse(aDbFileName);//this call may panic if aDbFileName cannot be parsed. But aDbFileName was preprocessed by TSqlSrvFileData::Set
|
sl@0
|
642 |
TFileName secureDbName;
|
sl@0
|
643 |
secureDbName.Copy(parse.Drive());
|
sl@0
|
644 |
secureDbName.Append(parse.NameAndExt());
|
sl@0
|
645 |
secureDbName.Append(TChar(0));
|
sl@0
|
646 |
TPtr8 ptr(iFileNameBuf, sizeof(iFileNameBuf));
|
sl@0
|
647 |
if(!::UTF16ZToUTF8Z(secureDbName, ptr))
|
sl@0
|
648 |
{
|
sl@0
|
649 |
__SQLLEAVE(KErrGeneral);
|
sl@0
|
650 |
}
|
sl@0
|
651 |
return iFileNameBuf;
|
sl@0
|
652 |
}
|
sl@0
|
653 |
|
sl@0
|
654 |
/**
|
sl@0
|
655 |
Attaches a secure or non-secure database to the current database connection.
|
sl@0
|
656 |
|
sl@0
|
657 |
@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
|
sl@0
|
658 |
file session reference and some other database file related properties.
|
sl@0
|
659 |
If this is a secure database, then the format of the name must be:
|
sl@0
|
660 |
\<drive\>:\<[SID]database file name excluding the path\>.
|
sl@0
|
661 |
If this is a non-secure database, then the file name has to be the full database file name.
|
sl@0
|
662 |
"[SID]" refers to SID of the application which creates the database.
|
sl@0
|
663 |
@param aDbName Database name. It must be unique (per database connection). This is the name which can
|
sl@0
|
664 |
be used for accessing tables in the attached database. The syntax is "database-name.table-name".
|
sl@0
|
665 |
|
sl@0
|
666 |
@leave KErrNotFound, the database file which has to be attached does not exist.
|
sl@0
|
667 |
KErrPermissionDenied, the client application does not satisfy the relevant security policies of
|
sl@0
|
668 |
the attached database.
|
sl@0
|
669 |
Note that the function may also leave with some other database specific
|
sl@0
|
670 |
errors categorised as ESqlDbError, and other system-wide error codes.
|
sl@0
|
671 |
|
sl@0
|
672 |
@see TSqlSrvFileData
|
sl@0
|
673 |
*/
|
sl@0
|
674 |
void CSqlSrvDatabase::AttachDbL(const TSqlSrvFileData& aFileData, const TDesC& aDbName)
|
sl@0
|
675 |
{
|
sl@0
|
676 |
SQL_TRACE_INTERNALS(OstTraceExt2(TRACE_INTERNALS, CSQLSRVDATABASE_ATTACHDBL_ENTRY, "Entry;0x%X;CSqlSrvDatabase::AttachDbL;aDbName=%S", (TUint)this, __SQLPRNSTR(aDbName)));
|
sl@0
|
677 |
if(!aFileData.ContainHandles())
|
sl@0
|
678 |
{//This check is valid only if the database is outside application's private data cage
|
sl@0
|
679 |
if(!::FileExists(aFileData.Fs(), aFileData.FileName()))
|
sl@0
|
680 |
{
|
sl@0
|
681 |
__SQLLEAVE(KErrNotFound);
|
sl@0
|
682 |
}
|
sl@0
|
683 |
}
|
sl@0
|
684 |
if(!aFileData.IsSecureFileNameFmt())
|
sl@0
|
685 |
{//A non-secure database to be attached - execute the "ATTACH DB" SQL statement and initialize the attached database.
|
sl@0
|
686 |
InitAttachedDbL(aFileData, aDbName);
|
sl@0
|
687 |
}
|
sl@0
|
688 |
else
|
sl@0
|
689 |
{//A secure database has to be attached. This is a complex operation and if it fails, proper cleanup
|
sl@0
|
690 |
//has to be performed. "state" variable keeps the state, after which the "attach db" operation failed.
|
sl@0
|
691 |
//There are three things needed to be done when atatching a secure database:
|
sl@0
|
692 |
// 1. Executing the "ATTACH DB" SQL statement and initializing the attached database
|
sl@0
|
693 |
// 2. Updating the security policy map
|
sl@0
|
694 |
// 3. Updating the {db name, logical db name} map
|
sl@0
|
695 |
//The additional map (3) is needed because when the authorizer callback is called by SQLITE, the callback
|
sl@0
|
696 |
//is given the logical database name, if that's an operation on an attached database. Since the security
|
sl@0
|
697 |
//policy map uses the database name as a key, the map (3) is used to find what is the physical database
|
sl@0
|
698 |
//name, which the logical database name points to.
|
sl@0
|
699 |
//
|
sl@0
|
700 |
//There is an additional step (0), which may happen when a secure database is attached to a
|
sl@0
|
701 |
//non-secure database. But this step does not require a cleanup.
|
sl@0
|
702 |
CSqlSrvDatabase::TAttachState state = CSqlSrvDatabase::EAStNone;
|
sl@0
|
703 |
const TUint8* securityMapKey = NULL;
|
sl@0
|
704 |
TRAPD(err, DoAttachSecureDbL(state, aFileData, aDbName, securityMapKey));
|
sl@0
|
705 |
if(err != KErrNone)
|
sl@0
|
706 |
{
|
sl@0
|
707 |
//Cleanup
|
sl@0
|
708 |
if(state > CSqlSrvDatabase::EAStNone)
|
sl@0
|
709 |
{
|
sl@0
|
710 |
(void)FinalizeAttachedDb(aDbName);
|
sl@0
|
711 |
if(state > CSqlSrvDatabase::EAStDbAttached)
|
sl@0
|
712 |
{
|
sl@0
|
713 |
::SqlServer().SecurityMap().Remove(securityMapKey);
|
sl@0
|
714 |
}
|
sl@0
|
715 |
}
|
sl@0
|
716 |
__SQLLEAVE(err);
|
sl@0
|
717 |
}
|
sl@0
|
718 |
}
|
sl@0
|
719 |
SQL_TRACE_INTERNALS(OstTrace1(TRACE_INTERNALS, CSQLSRVDATABASE_ATTACHDBL_EXIT, "Exit;0x%X;CSqlSrvDatabase::AttachDbL", (TUint)this));
|
sl@0
|
720 |
}
|
sl@0
|
721 |
|
sl@0
|
722 |
/**
|
sl@0
|
723 |
Attaches a secure database to the existing connection.
|
sl@0
|
724 |
|
sl@0
|
725 |
The function also updates the following maps:
|
sl@0
|
726 |
- Security policies map (CSqlServer::iSecurityMap), where a reference counted copy of database security policies
|
sl@0
|
727 |
is kept for each created/opened/attached database during the life time of the SQL server;
|
sl@0
|
728 |
- Attached secure databases map (CSqlSrvDatabase::iAttachDbMap), where an information is kept what SQL database
|
sl@0
|
729 |
file name corresponds to a specific attached database name. This information is used by the authorizer callback
|
sl@0
|
730 |
function in order to find what database security policies have to be asserted when a SQL operation is issued
|
sl@0
|
731 |
for a particular attached database (the attached database name is identified always by its name, not the file name);
|
sl@0
|
732 |
|
sl@0
|
733 |
@param aState Output parameter - the attach progress state, used by the calling function to perform correctly
|
sl@0
|
734 |
the cleanup, if the attach operation fails.
|
sl@0
|
735 |
It may have the following values set:
|
sl@0
|
736 |
- CSqlSrvDatabase::EAStNone - no resources need to be freed;
|
sl@0
|
737 |
- CSqlSrvDatabase::EAStDbAttached - the function was able to execute the "ATTACH DATABASE"
|
sl@0
|
738 |
SQL statement before an error occured. The calling function has to execute "DETACH DATABASE"
|
sl@0
|
739 |
SQL statement to detach the database;
|
sl@0
|
740 |
- CSqlSrvDatabase::EAStSecurityMapUpdated - the function was able to update the security policies
|
sl@0
|
741 |
map (CSqlServer::iSecurityMap) before an error occured. The calling function has to remove
|
sl@0
|
742 |
the attached database security policies from the map and detach the database.
|
sl@0
|
743 |
@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
|
sl@0
|
744 |
file session reference and some other database file related properties.
|
sl@0
|
745 |
The secure database name format must be:
|
sl@0
|
746 |
\<drive\>:\<[SID]database file name excluding the path\>.
|
sl@0
|
747 |
"[SID]" refers to SID of the application which creates the database.
|
sl@0
|
748 |
@param aDbName Database name. It must be unique (per database connection). This is the name which can
|
sl@0
|
749 |
be used for accessing tables in the attached database. The syntax is "database-name.table-name".
|
sl@0
|
750 |
@param aMapKey Output parameter, UTF8 encoded, zero-terminated string, which can be used for searching
|
sl@0
|
751 |
of the attached database security policies in the security policies map (CSqlServer::iSecurityMap).
|
sl@0
|
752 |
No memory is allocated for the key.
|
sl@0
|
753 |
|
sl@0
|
754 |
@see RSqlSecurityMap
|
sl@0
|
755 |
@see RSqlAttachDbMap
|
sl@0
|
756 |
@see CSqlServer
|
sl@0
|
757 |
@see TSqlSrvFileData
|
sl@0
|
758 |
@see CSqlSrvDatabase
|
sl@0
|
759 |
|
sl@0
|
760 |
@leave KErrNoMemory, an out of memory condition has occurred;
|
sl@0
|
761 |
KErrPermissionDenied, the client application does not satisfy the relevant security policies of
|
sl@0
|
762 |
the attached database.
|
sl@0
|
763 |
Note that the function may also leave with some other database specific
|
sl@0
|
764 |
errors categorised as ESqlDbError, and other system-wide error codes.
|
sl@0
|
765 |
*/
|
sl@0
|
766 |
void CSqlSrvDatabase::DoAttachSecureDbL(CSqlSrvDatabase::TAttachState& aState,
|
sl@0
|
767 |
const TSqlSrvFileData& aFileData,
|
sl@0
|
768 |
const TDesC& aDbName, const TUint8*& aMapKey)
|
sl@0
|
769 |
{
|
sl@0
|
770 |
//Step 1: Attach the database and initialize the attached database
|
sl@0
|
771 |
InitAttachedDbL(aFileData, aDbName);
|
sl@0
|
772 |
aState = CSqlSrvDatabase::EAStDbAttached;
|
sl@0
|
773 |
//Step 2: Load the database security policy and update the security map
|
sl@0
|
774 |
const CSqlSecurityPolicy* securityPolicy = NULL;
|
sl@0
|
775 |
UpdateSecurityMapL(ETrue, aFileData, aMapKey, securityPolicy);
|
sl@0
|
776 |
aState = CSqlSrvDatabase::EAStSecurityMapUpdated;
|
sl@0
|
777 |
//Check that the caller has at least one of {Schema, Read, Write} policies.
|
sl@0
|
778 |
BasicSecurityPolicyCheckL(*securityPolicy);
|
sl@0
|
779 |
//Step 3: Update the attached databases map
|
sl@0
|
780 |
InsertInAttachDbMapL(aFileData.FileName(), aDbName);
|
sl@0
|
781 |
}
|
sl@0
|
782 |
|
sl@0
|
783 |
/**
|
sl@0
|
784 |
Detaches a database from the current database connection.
|
sl@0
|
785 |
|
sl@0
|
786 |
The function also will search the security policies map (CSqlServer::iSecurityMap) and the attached databases
|
sl@0
|
787 |
map (CSqlSrvDatabase::iAttachDbMap) for entries which correspond to the database ,
|
sl@0
|
788 |
which is about to be detached, and will remove the entries.
|
sl@0
|
789 |
|
sl@0
|
790 |
@param aDbName Attached database name. It must be unique (per database connection).
|
sl@0
|
791 |
|
sl@0
|
792 |
@leave The function may leave with some database specific errors categorised as ESqlDbError,
|
sl@0
|
793 |
and other system-wide error codes.
|
sl@0
|
794 |
|
sl@0
|
795 |
@see CSqlSrvDatabase::DoAttachSecureDbL()
|
sl@0
|
796 |
@see RSqlSecurityMap
|
sl@0
|
797 |
@see RSqlAttachDbMap
|
sl@0
|
798 |
@see CSqlServer
|
sl@0
|
799 |
@see CSqlSrvDatabase
|
sl@0
|
800 |
*/
|
sl@0
|
801 |
void CSqlSrvDatabase::DetachDbL(const TDesC& aDbName)
|
sl@0
|
802 |
{
|
sl@0
|
803 |
SQL_TRACE_INTERNALS(OstTraceExt2(TRACE_INTERNALS, CSQLSRVDATABASE_DETACHDBL_ENTRY, "Entry;0x%X;CSqlSrvDatabase::DetachDbL;aDbName=%S", (TUint)this, __SQLPRNSTR(aDbName)));
|
sl@0
|
804 |
TInt err = FinalizeAttachedDb(aDbName);
|
sl@0
|
805 |
if(err == KErrNone)
|
sl@0
|
806 |
{
|
sl@0
|
807 |
TRAP_IGNORE(RemoveFromMapsL(aDbName));
|
sl@0
|
808 |
}
|
sl@0
|
809 |
else
|
sl@0
|
810 |
{
|
sl@0
|
811 |
__SQLLEAVE(err);
|
sl@0
|
812 |
}
|
sl@0
|
813 |
SQL_TRACE_INTERNALS(OstTrace1(TRACE_INTERNALS, CSQLSRVDATABASE_DETACHDBL_EXIT, "Exit;0x%X;CSqlSrvDatabase::DetachDbL", (TUint)this));
|
sl@0
|
814 |
}
|
sl@0
|
815 |
|
sl@0
|
816 |
/**
|
sl@0
|
817 |
Calculates and returns the database size.
|
sl@0
|
818 |
|
sl@0
|
819 |
@param aDbName Attached database name or KNullDesC for the main database
|
sl@0
|
820 |
|
sl@0
|
821 |
@leave The function may leave with some database specific errors categorised as ESqlDbError,
|
sl@0
|
822 |
and other system-wide error codes.
|
sl@0
|
823 |
|
sl@0
|
824 |
@return Database size in bytes.
|
sl@0
|
825 |
*/
|
sl@0
|
826 |
TInt64 CSqlSrvDatabase::SizeL(const TDesC& aDbName)
|
sl@0
|
827 |
{
|
sl@0
|
828 |
iAuthorizerDisabled = ETrue;
|
sl@0
|
829 |
CleanupStack::PushL(TCleanupItem(&EnableAuthorizer, &iAuthorizerDisabled));
|
sl@0
|
830 |
TInt pageCount = 0;
|
sl@0
|
831 |
__SQLLEAVE_IF_ERROR(::DbPageCount(iDbHandle, aDbName, pageCount));
|
sl@0
|
832 |
__ASSERT_DEBUG(pageCount >= 0, __SQLPANIC(ESqlPanicInternalError));
|
sl@0
|
833 |
CleanupStack::PopAndDestroy();
|
sl@0
|
834 |
return (TInt64)pageCount * PageSizeL(aDbName);
|
sl@0
|
835 |
}
|
sl@0
|
836 |
|
sl@0
|
837 |
/**
|
sl@0
|
838 |
Retrieves the database free space.
|
sl@0
|
839 |
|
sl@0
|
840 |
@param aDbName Attached database name or KNullDesC for the main database
|
sl@0
|
841 |
|
sl@0
|
842 |
@return Database free space in bytes.
|
sl@0
|
843 |
|
sl@0
|
844 |
@leave The function may leave with some database specific errors categorised as ESqlDbError,
|
sl@0
|
845 |
and other system-wide error codes.
|
sl@0
|
846 |
*/
|
sl@0
|
847 |
TInt64 CSqlSrvDatabase::FreeSpaceL(const TDesC& aDbName)
|
sl@0
|
848 |
{
|
sl@0
|
849 |
iAuthorizerDisabled = ETrue;
|
sl@0
|
850 |
CleanupStack::PushL(TCleanupItem(&EnableAuthorizer, &iAuthorizerDisabled));
|
sl@0
|
851 |
TInt freePageCount = 0;
|
sl@0
|
852 |
__SQLLEAVE_IF_ERROR(::DbFreePageCount(iDbHandle, aDbName, freePageCount));
|
sl@0
|
853 |
CleanupStack::PopAndDestroy();
|
sl@0
|
854 |
__ASSERT_DEBUG(freePageCount >= 0, __SQLPANIC(ESqlPanicInternalError));
|
sl@0
|
855 |
return (TInt64)freePageCount * PageSizeL(aDbName);
|
sl@0
|
856 |
}
|
sl@0
|
857 |
|
sl@0
|
858 |
/**
|
sl@0
|
859 |
Collects information regarding the current cache size, page, size, encoding, etc. and puts the values
|
sl@0
|
860 |
in the aDest output string.
|
sl@0
|
861 |
|
sl@0
|
862 |
@param aDest Output parameter, where the result values will be stored. The string format is: "<val1>;<val2>...;".
|
sl@0
|
863 |
|
sl@0
|
864 |
@leave The function may leave with some database specific errors categorised as ESqlDbError,
|
sl@0
|
865 |
and other system-wide error codes.
|
sl@0
|
866 |
*/
|
sl@0
|
867 |
void CSqlSrvDatabase::QueryConfigL(TDes8& aDest)
|
sl@0
|
868 |
{
|
sl@0
|
869 |
iAuthorizerDisabled = ETrue;
|
sl@0
|
870 |
CleanupStack::PushL(TCleanupItem(&EnableAuthorizer, &iAuthorizerDisabled));
|
sl@0
|
871 |
|
sl@0
|
872 |
TInt cacheSize = 0;
|
sl@0
|
873 |
__SQLLEAVE_IF_ERROR(::DbCacheSize(iDbHandle, KNullDesC, cacheSize));
|
sl@0
|
874 |
|
sl@0
|
875 |
TInt pageSize = 0;
|
sl@0
|
876 |
__SQLLEAVE_IF_ERROR(::DbPageSize(iDbHandle, KNullDesC, pageSize));
|
sl@0
|
877 |
|
sl@0
|
878 |
TBuf8<16> encoding;
|
sl@0
|
879 |
__SQLLEAVE_IF_ERROR(::DbEncoding(iDbHandle, KNullDesC, encoding));
|
sl@0
|
880 |
|
sl@0
|
881 |
TInt defaultSoftHeapLimit = TSqlSrvConfigParams::KDefaultSoftHeapLimitKb;
|
sl@0
|
882 |
|
sl@0
|
883 |
TInt vacuum = 0;
|
sl@0
|
884 |
__SQLLEAVE_IF_ERROR(::DbVacuumMode(iDbHandle, KNullDesC, vacuum));
|
sl@0
|
885 |
|
sl@0
|
886 |
aDest.AppendNum(cacheSize);
|
sl@0
|
887 |
_LIT8(KSemiColon, ";");
|
sl@0
|
888 |
aDest.Append(KSemiColon);
|
sl@0
|
889 |
aDest.AppendNum(pageSize);
|
sl@0
|
890 |
aDest.Append(KSemiColon);
|
sl@0
|
891 |
aDest.Append(encoding);
|
sl@0
|
892 |
aDest.Append(KSemiColon);
|
sl@0
|
893 |
aDest.AppendNum(defaultSoftHeapLimit);
|
sl@0
|
894 |
aDest.Append(KSemiColon);
|
sl@0
|
895 |
aDest.AppendNum(vacuum);
|
sl@0
|
896 |
aDest.Append(KSemiColon);
|
sl@0
|
897 |
|
sl@0
|
898 |
CleanupStack::PopAndDestroy();
|
sl@0
|
899 |
}
|
sl@0
|
900 |
|
sl@0
|
901 |
/**
|
sl@0
|
902 |
Compacts the database free space.
|
sl@0
|
903 |
|
sl@0
|
904 |
@param aSize The requested database space to be compacted, in bytes.
|
sl@0
|
905 |
If aSize value is RSqlDatabase::EMaxCompaction, then all free pages will be removed.
|
sl@0
|
906 |
Note that the requested space to be compacted will be rounded up to the nearest page count,
|
sl@0
|
907 |
e.g. request for removing 1 byte will remove one free page from the database file.
|
sl@0
|
908 |
|
sl@0
|
909 |
@param aDbName Attached database name or KNullDesC for the main database
|
sl@0
|
910 |
|
sl@0
|
911 |
@return The size of the removed free space
|
sl@0
|
912 |
|
sl@0
|
913 |
@leave The function may leave with some database specific errors categorised as ESqlDbError,
|
sl@0
|
914 |
and other system-wide error codes.
|
sl@0
|
915 |
*/
|
sl@0
|
916 |
TInt CSqlSrvDatabase::CompactL(TInt aSize, const TDesC& aDbName)
|
sl@0
|
917 |
{
|
sl@0
|
918 |
SQL_TRACE_INTERNALS(OstTraceExt3(TRACE_INTERNALS, CSQLSRVDATABASE_COMPACTL_ENTRY, "Entry;0x%X;CSqlSrvDatabase::CompactL;aSize=%d;aDbName=%S", (TUint)this, aSize, __SQLPRNSTR(aDbName)));
|
sl@0
|
919 |
__ASSERT_DEBUG(aSize > 0 || aSize == RSqlDatabase::EMaxCompaction, __SQLPANIC(ESqlPanicBadArgument));
|
sl@0
|
920 |
TInt pageSize = PageSizeL(aDbName);//PageSizeL() will disable/enable the authorizer
|
sl@0
|
921 |
TInt pageCount = KMaxTInt;
|
sl@0
|
922 |
if(aSize > 0)
|
sl@0
|
923 |
{//64-bit calculations to avoid the overflow in case if (aSize + pageSize) >= KMaxTInt.
|
sl@0
|
924 |
pageCount = (TInt64)((TInt64)aSize + pageSize - 1) / pageSize;
|
sl@0
|
925 |
}
|
sl@0
|
926 |
if(pageCount > 0)
|
sl@0
|
927 |
{
|
sl@0
|
928 |
iAuthorizerDisabled = ETrue;
|
sl@0
|
929 |
CleanupStack::PushL(TCleanupItem(&EnableAuthorizer, &iAuthorizerDisabled));
|
sl@0
|
930 |
__SQLLEAVE_IF_ERROR(::DbCompact(iDbHandle, aDbName, pageCount, pageCount));
|
sl@0
|
931 |
CleanupStack::PopAndDestroy();
|
sl@0
|
932 |
}
|
sl@0
|
933 |
SQL_TRACE_INTERNALS(OstTraceExt3(TRACE_INTERNALS, CSQLSRVDATABASE_COMPACTL_EXIT, "Exit;0x%X;CSqlSrvDatabase::CompactL;pageCount=%d;pageSize=%d", (TUint)this, pageCount, pageSize));
|
sl@0
|
934 |
return pageCount * pageSize;
|
sl@0
|
935 |
}
|
sl@0
|
936 |
|
sl@0
|
937 |
/**
|
sl@0
|
938 |
This structure is used in case if the InitAttachedDbL() execution fails and the
|
sl@0
|
939 |
executed operations ("attach database", "init compact") have to be reverted calling
|
sl@0
|
940 |
FinalizeAttachedDb().
|
sl@0
|
941 |
|
sl@0
|
942 |
@see CSqlSrvDatabase::InitAttachedDbL
|
sl@0
|
943 |
@see CSqlSrvDatabase::FinalizeAttachedDb
|
sl@0
|
944 |
@see CSqlSrvDatabase::AttachCleanup
|
sl@0
|
945 |
|
sl@0
|
946 |
@internalComponent
|
sl@0
|
947 |
*/
|
sl@0
|
948 |
NONSHARABLE_STRUCT(TAttachCleanup)
|
sl@0
|
949 |
{
|
sl@0
|
950 |
inline TAttachCleanup(CSqlSrvDatabase& aSelf, const TDesC& aDbName) :
|
sl@0
|
951 |
iSelf(aSelf),
|
sl@0
|
952 |
iDbName(aDbName)
|
sl@0
|
953 |
{
|
sl@0
|
954 |
}
|
sl@0
|
955 |
CSqlSrvDatabase& iSelf;
|
sl@0
|
956 |
const TDesC& iDbName;
|
sl@0
|
957 |
};
|
sl@0
|
958 |
|
sl@0
|
959 |
/**
|
sl@0
|
960 |
Cleanup function. Calls FinalizeAttachedDb() if InitAttachedDbL() has failed.
|
sl@0
|
961 |
|
sl@0
|
962 |
@param aCleanup A pointer to a TAttachCleanup object that contains the needed for the cleanup information.
|
sl@0
|
963 |
|
sl@0
|
964 |
@see TAttachCleanup
|
sl@0
|
965 |
|
sl@0
|
966 |
@internalComponent
|
sl@0
|
967 |
*/
|
sl@0
|
968 |
void CSqlSrvDatabase::AttachCleanup(void* aCleanup)
|
sl@0
|
969 |
{
|
sl@0
|
970 |
TAttachCleanup* cleanup = reinterpret_cast <TAttachCleanup*> (aCleanup);
|
sl@0
|
971 |
__ASSERT_DEBUG(cleanup != NULL, __SQLPANIC2(ESqlPanicBadArgument));
|
sl@0
|
972 |
(void)cleanup->iSelf.FinalizeAttachedDb(cleanup->iDbName);
|
sl@0
|
973 |
}
|
sl@0
|
974 |
|
sl@0
|
975 |
/**
|
sl@0
|
976 |
Forms and executes "ATTACH DATABASE" SQL statement.
|
sl@0
|
977 |
If the database is not read-only:
|
sl@0
|
978 |
- Makes the attached database journal file persistent.
|
sl@0
|
979 |
- Initializes the attached database compaction mode.
|
sl@0
|
980 |
- The attached database will be reindexed if the default collation has been changed.
|
sl@0
|
981 |
|
sl@0
|
982 |
@param aFileData Attached database file data
|
sl@0
|
983 |
@param aDbName Attached database name. It must be unique (per database connection).
|
sl@0
|
984 |
|
sl@0
|
985 |
@leave KErrNoMemory, an out of memory condition has occurred;
|
sl@0
|
986 |
Note that the function may also leave with some other database specific
|
sl@0
|
987 |
errors categorised as ESqlDbError, and other system-wide error codes.
|
sl@0
|
988 |
|
sl@0
|
989 |
@see InitCompactionL
|
sl@0
|
990 |
@see ProcessSettingsL
|
sl@0
|
991 |
*/
|
sl@0
|
992 |
void CSqlSrvDatabase::InitAttachedDbL(const TSqlSrvFileData& aFileData, const TDesC& aDbName)
|
sl@0
|
993 |
{
|
sl@0
|
994 |
TPtrC dbFileName = aFileData.FileName();
|
sl@0
|
995 |
TBool readOnlyDbFile = aFileData.IsReadOnly();
|
sl@0
|
996 |
|
sl@0
|
997 |
InstallAuthorizerL();
|
sl@0
|
998 |
iAuthorizerDisabled = ETrue;
|
sl@0
|
999 |
CleanupStack::PushL(TCleanupItem(&EnableAuthorizer, &iAuthorizerDisabled));
|
sl@0
|
1000 |
sqlite3_stmt* stmtHandle = StmtPrepare16L(iDbHandle, KAttachDb);
|
sl@0
|
1001 |
TInt err = ::Sql2OsErrCode(sqlite3_bind_text16(stmtHandle, 1, dbFileName.Ptr(), dbFileName.Length() * sizeof(TUint16), SQLITE_STATIC), sqlite3SymbianLastOsError());
|
sl@0
|
1002 |
if(err == KErrNone)
|
sl@0
|
1003 |
{
|
sl@0
|
1004 |
err = ::Sql2OsErrCode(sqlite3_bind_text16(stmtHandle, 2, aDbName.Ptr(), aDbName.Length() * sizeof(TUint16), SQLITE_STATIC), sqlite3SymbianLastOsError());
|
sl@0
|
1005 |
if(err == KErrNone)
|
sl@0
|
1006 |
{
|
sl@0
|
1007 |
err = StmtExec(stmtHandle);
|
sl@0
|
1008 |
}
|
sl@0
|
1009 |
}
|
sl@0
|
1010 |
(void)::FinalizeStmtHandle(stmtHandle);//sqlite3_finalize() fails only if an invalid statement handle is passed.
|
sl@0
|
1011 |
CleanupStack::PopAndDestroy();//TCleanupItem(&EnableAuthorizer, &iAuthorizerDisabled)
|
sl@0
|
1012 |
__SQLLEAVE_IF_ERROR(err);
|
sl@0
|
1013 |
|
sl@0
|
1014 |
TAttachCleanup attachCleanup(*this, aDbName);
|
sl@0
|
1015 |
CleanupStack::PushL(TCleanupItem(&CSqlSrvDatabase::AttachCleanup, &attachCleanup));
|
sl@0
|
1016 |
|
sl@0
|
1017 |
SetConfigL(aFileData.ConfigParams(), EFalse, aDbName);
|
sl@0
|
1018 |
|
sl@0
|
1019 |
if(!readOnlyDbFile)
|
sl@0
|
1020 |
{
|
sl@0
|
1021 |
iAuthorizerDisabled = ETrue;
|
sl@0
|
1022 |
CleanupStack::PushL(TCleanupItem(&EnableAuthorizer, &iAuthorizerDisabled));
|
sl@0
|
1023 |
ProcessSettingsL(aFileData, aDbName);
|
sl@0
|
1024 |
CleanupStack::PopAndDestroy();//TCleanupItem(&EnableAuthorizer, &iAuthorizerDisabled)
|
sl@0
|
1025 |
}
|
sl@0
|
1026 |
|
sl@0
|
1027 |
CleanupStack::Pop();//TCleanupItem(&CSqlSrvDatabase::AttachCleanup, &attachCleanup)
|
sl@0
|
1028 |
}
|
sl@0
|
1029 |
|
sl@0
|
1030 |
/**
|
sl@0
|
1031 |
Forms and executes "DETACH DATABASE" SQL statement.
|
sl@0
|
1032 |
If the database was scheduled for background compacting, the related database entry will be removed from
|
sl@0
|
1033 |
the vaccum db map.
|
sl@0
|
1034 |
|
sl@0
|
1035 |
@param aDbName Attached database name. It must be unique (per database connection).
|
sl@0
|
1036 |
|
sl@0
|
1037 |
@return KErrNone, Operation completed successfully;
|
sl@0
|
1038 |
KErrNoMemory, an out of memory condition has occurred.
|
sl@0
|
1039 |
Note that the function may also return some other database specific
|
sl@0
|
1040 |
errors categorised as ESqlDbError, and other system-wide error codes.
|
sl@0
|
1041 |
*/
|
sl@0
|
1042 |
TInt CSqlSrvDatabase::FinalizeAttachedDb(const TDesC& aDbName)
|
sl@0
|
1043 |
{
|
sl@0
|
1044 |
ReleaseCompactEntry(aDbName);
|
sl@0
|
1045 |
iAuthorizerDisabled = ETrue;
|
sl@0
|
1046 |
sqlite3_stmt* stmtHandle = NULL;
|
sl@0
|
1047 |
TRAPD(err, stmtHandle = StmtPrepare16L(iDbHandle, KDetachDb));
|
sl@0
|
1048 |
if(err == KErrNone)
|
sl@0
|
1049 |
{
|
sl@0
|
1050 |
err = ::Sql2OsErrCode(sqlite3_bind_text16(stmtHandle, 1, aDbName.Ptr(), aDbName.Length() * sizeof(TUint16), SQLITE_STATIC), sqlite3SymbianLastOsError());
|
sl@0
|
1051 |
if(err == KErrNone)
|
sl@0
|
1052 |
{
|
sl@0
|
1053 |
err = StmtExec(stmtHandle);
|
sl@0
|
1054 |
}
|
sl@0
|
1055 |
}
|
sl@0
|
1056 |
(void)::FinalizeStmtHandle(stmtHandle);//sqlite3_finalize() fails only if an invalid statement handle is passed.
|
sl@0
|
1057 |
iAuthorizerDisabled = EFalse;
|
sl@0
|
1058 |
return err;
|
sl@0
|
1059 |
}
|
sl@0
|
1060 |
|
sl@0
|
1061 |
/**
|
sl@0
|
1062 |
Updates the security policies map (CSqlServer::iSecurityMap).
|
sl@0
|
1063 |
|
sl@0
|
1064 |
Inserts a new item in the security map, or if such item already exists there - its reference counter will
|
sl@0
|
1065 |
be incremented.
|
sl@0
|
1066 |
The method guarantees that either the security map will be updated, or the method leaves and the security
|
sl@0
|
1067 |
policies map stays unchanged.
|
sl@0
|
1068 |
|
sl@0
|
1069 |
@param aAttachedDb True if the currently processed database is an attached database, false if it is the main db.
|
sl@0
|
1070 |
@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
|
sl@0
|
1071 |
file session reference and some other database file related properties.
|
sl@0
|
1072 |
The secure database name format must be:
|
sl@0
|
1073 |
\<drive\>:\<[SID]database file name excluding the path\>.
|
sl@0
|
1074 |
"[SID]" refers to SID of the application which creates the database.
|
sl@0
|
1075 |
@param aMapKey Output parameter. UTF8 encoded, zero-terminated string. On function exit cannot be NULL.
|
sl@0
|
1076 |
It will be set to point to the security policies map key. No memory is allocated for the key.
|
sl@0
|
1077 |
@param aSecurityPolicy Output parameter. On function exit cannot be NULL. It will be set to point to the security policies.
|
sl@0
|
1078 |
|
sl@0
|
1079 |
@leave KErrNoMemory, an out of memory condition has occurred;
|
sl@0
|
1080 |
Note that the function may also leave with some other database specific
|
sl@0
|
1081 |
errors categorised as ESqlDbError, and other system-wide error codes.
|
sl@0
|
1082 |
|
sl@0
|
1083 |
@see RSqlSecurityMap
|
sl@0
|
1084 |
@see CSqlServer
|
sl@0
|
1085 |
@see TSqlSrvFileData
|
sl@0
|
1086 |
@see CSqlSecurityPolicy
|
sl@0
|
1087 |
*/
|
sl@0
|
1088 |
void CSqlSrvDatabase::UpdateSecurityMapL(TBool aAttachedDb, const TSqlSrvFileData& aFileData,
|
sl@0
|
1089 |
const TUint8*& aMapKey, const CSqlSecurityPolicy*& aSecurityPolicy)
|
sl@0
|
1090 |
{
|
sl@0
|
1091 |
//Check if a copy of the database security policies is already in the security map.
|
sl@0
|
1092 |
aMapKey = SecurityMapKeyL(aFileData.FileName());
|
sl@0
|
1093 |
TSqlSecurityPair* pair = ::SqlServer().SecurityMap().Entry(aMapKey);
|
sl@0
|
1094 |
if(pair)
|
sl@0
|
1095 |
{
|
sl@0
|
1096 |
//Yes, it is in the map. Increment the reference counter.
|
sl@0
|
1097 |
//(It will be decremented when detaching the database).
|
sl@0
|
1098 |
pair->iRefCounter.Increment();
|
sl@0
|
1099 |
aMapKey = pair->iKey;
|
sl@0
|
1100 |
aSecurityPolicy = pair->iData;
|
sl@0
|
1101 |
}
|
sl@0
|
1102 |
else
|
sl@0
|
1103 |
{
|
sl@0
|
1104 |
//No, it is not in the map. Read the security policies from the security policies tables and
|
sl@0
|
1105 |
//insert a new item in the map.
|
sl@0
|
1106 |
__ASSERT_DEBUG(aMapKey != NULL, __SQLPANIC(ESqlPanicInternalError));
|
sl@0
|
1107 |
aMapKey = ::CreateStrCopyLC(aMapKey);
|
sl@0
|
1108 |
CSqlSecurityPolicy* securityPolicy = aAttachedDb ? ::LoadAttachedDbSecurityPolicyLC(aFileData) :
|
sl@0
|
1109 |
::LoadDbSecurityPolicyLC(iDbHandle);
|
sl@0
|
1110 |
__ASSERT_DEBUG(!::SqlServer().SecurityMap().Entry(aMapKey), __SQLPANIC2(ESqlPanicObjExists));
|
sl@0
|
1111 |
__SQLLEAVE_IF_ERROR(::SqlServer().SecurityMap().Insert(aMapKey, securityPolicy));
|
sl@0
|
1112 |
CleanupStack::Pop(2);//iSecurityMap owns aMapKey and securityPolicy objects
|
sl@0
|
1113 |
aSecurityPolicy = securityPolicy;
|
sl@0
|
1114 |
}
|
sl@0
|
1115 |
__ASSERT_DEBUG(aMapKey != NULL, __SQLPANIC(ESqlPanicInternalError));
|
sl@0
|
1116 |
__ASSERT_DEBUG(aSecurityPolicy != NULL, __SQLPANIC(ESqlPanicInternalError));
|
sl@0
|
1117 |
}
|
sl@0
|
1118 |
|
sl@0
|
1119 |
/**
|
sl@0
|
1120 |
Removes attached secure database entries from the maps.
|
sl@0
|
1121 |
|
sl@0
|
1122 |
The function will search the security policies map (CSqlServer::iSecurityMap) and the attached databases
|
sl@0
|
1123 |
map (CSqlSrvDatabase::iAttachDbMap) for entries which correspond to the database with aDbName name,
|
sl@0
|
1124 |
and will remove the entries.
|
sl@0
|
1125 |
|
sl@0
|
1126 |
The sequence of the performed by the function operations is:
|
sl@0
|
1127 |
1. Looks for a map item which key is aDbName in iAttachDbMap map.
|
sl@0
|
1128 |
2. If such pair exists, the data part of the pair is used as a key in iSecurityMap map.
|
sl@0
|
1129 |
3. Remove the iSecurityMap map item pointed by the data part of the found pair.
|
sl@0
|
1130 |
4. Remove the iAttachDbMap map item pointed by aDbName.
|
sl@0
|
1131 |
|
sl@0
|
1132 |
@param aDbName Attached database name. It must be unique (per database connection).
|
sl@0
|
1133 |
|
sl@0
|
1134 |
@leave KErrGeneral It is not possible to convert aDbName parameter to UTF8 encoded string.
|
sl@0
|
1135 |
|
sl@0
|
1136 |
@see CSqlSrvDatabase::DoAttachDbL()
|
sl@0
|
1137 |
@see CSqlSrvDatabase::DoAttachSecureDbL()
|
sl@0
|
1138 |
@see RSqlSecurityMap
|
sl@0
|
1139 |
@see RSqlAttachDbMap
|
sl@0
|
1140 |
@see CSqlServer
|
sl@0
|
1141 |
@see CSqlSrvDatabase
|
sl@0
|
1142 |
*/
|
sl@0
|
1143 |
void CSqlSrvDatabase::RemoveFromMapsL(const TDesC& aDbName)
|
sl@0
|
1144 |
{
|
sl@0
|
1145 |
SQL_TRACE_INTERNALS(OstTraceExt2(TRACE_INTERNALS, CSQLSRVDATABASE_REMOVEFROMMAPSL, "0x%X;CSqlSrvDatabase::RemoveFromMapsL;aDbName=%S", (TUint)this, __SQLPRNSTR(aDbName)));
|
sl@0
|
1146 |
TPtr8 ptr(iFileNameBuf, sizeof(iFileNameBuf));
|
sl@0
|
1147 |
if(!::UTF16ToUTF8Z(aDbName, ptr))
|
sl@0
|
1148 |
{
|
sl@0
|
1149 |
__SQLLEAVE(KErrGeneral);
|
sl@0
|
1150 |
}
|
sl@0
|
1151 |
TSqlAttachDbPair* attachDbPair = iAttachDbMap.Entry(iFileNameBuf);
|
sl@0
|
1152 |
if(attachDbPair)
|
sl@0
|
1153 |
{//aDbName refers to attached secure database
|
sl@0
|
1154 |
::SqlServer().SecurityMap().Remove(attachDbPair->iData);
|
sl@0
|
1155 |
iAttachDbMap.Remove(iFileNameBuf);
|
sl@0
|
1156 |
}
|
sl@0
|
1157 |
}
|
sl@0
|
1158 |
|
sl@0
|
1159 |
/**
|
sl@0
|
1160 |
Inserts a new entry in the attached databases map (CSqlSrvDatabase::iAttachDbMap).
|
sl@0
|
1161 |
|
sl@0
|
1162 |
The method guarantees that either a new [logical db name, secure db name] pair will be inserted in
|
sl@0
|
1163 |
iAttachDbMap or the method fails and the content of iAttachDbMap remains unchanged.
|
sl@0
|
1164 |
|
sl@0
|
1165 |
@param aDbFileName Database file name, including the path.
|
sl@0
|
1166 |
@param aDbName Database name.
|
sl@0
|
1167 |
|
sl@0
|
1168 |
@leave KErrNoMemory, an out of memory condition has occurred;
|
sl@0
|
1169 |
KErrGeneral, it is not possible to convert the function parameters to UTF8 encoded strings.
|
sl@0
|
1170 |
|
sl@0
|
1171 |
@see RSqlAttachDbMap
|
sl@0
|
1172 |
@see CSqlSrvDatabase
|
sl@0
|
1173 |
*/
|
sl@0
|
1174 |
void CSqlSrvDatabase::InsertInAttachDbMapL(const TDesC& aDbFileName, const TDesC& aDbName)
|
sl@0
|
1175 |
{
|
sl@0
|
1176 |
SQL_TRACE_INTERNALS(OstTraceExt3(TRACE_INTERNALS, CSQLSRVDATABASE_INSERTINATTACHDBMAPL, "0x%X;CSqlSrvDatabase::InsertInAttachDbMapL;aDbFileName=%S;aDbName=%S", (TUint)this, __SQLPRNSTR(aDbFileName), __SQLPRNSTR(aDbName)));
|
sl@0
|
1177 |
//Convert aDbName to UTF8, zero-terminated name
|
sl@0
|
1178 |
TPtr8 ptr(iFileNameBuf, sizeof(iFileNameBuf));
|
sl@0
|
1179 |
if(!::UTF16ToUTF8Z(aDbName, ptr))
|
sl@0
|
1180 |
{
|
sl@0
|
1181 |
__SQLLEAVE(KErrGeneral);
|
sl@0
|
1182 |
}
|
sl@0
|
1183 |
const TUint8* mapKey = ::CreateStrCopyLC(iFileNameBuf);
|
sl@0
|
1184 |
const TUint8* mapData = SecurityMapKeyL(aDbFileName);
|
sl@0
|
1185 |
mapData = ::CreateStrCopyLC(mapData);
|
sl@0
|
1186 |
__ASSERT_DEBUG(!iAttachDbMap.Entry(mapKey), __SQLPANIC(ESqlPanicObjExists));
|
sl@0
|
1187 |
__SQLLEAVE_IF_ERROR(iAttachDbMap.Insert(mapKey, mapData));
|
sl@0
|
1188 |
CleanupStack::Pop(2);//iAttachDbMap owns mapKey amd mapData.
|
sl@0
|
1189 |
}
|
sl@0
|
1190 |
|
sl@0
|
1191 |
/**
|
sl@0
|
1192 |
Processes the database settings that are currently stored in the settings table.
|
sl@0
|
1193 |
Makes the journal file persistent.
|
sl@0
|
1194 |
Initializes the database compaction mode.
|
sl@0
|
1195 |
Based on the current settings the database may be configured to become 'up-to-date'.
|
sl@0
|
1196 |
This configuration may include reindexing the database if the collation dll has
|
sl@0
|
1197 |
changed and/or executing database configuration file operations.
|
sl@0
|
1198 |
|
sl@0
|
1199 |
@param aFileData The file data object,
|
sl@0
|
1200 |
@param aDbName Logical database name: "main" for the main database or attached database name,
|
sl@0
|
1201 |
|
sl@0
|
1202 |
@leave The function may leave with system-wide error codes or SQL errors of ESqlDbError type
|
sl@0
|
1203 |
|
sl@0
|
1204 |
@panic SqlDb 7 In _DEBUG mode if aFileData does not refer to a r/w database file.
|
sl@0
|
1205 |
*/
|
sl@0
|
1206 |
void CSqlSrvDatabase::ProcessSettingsL(const TSqlSrvFileData& aFileData, const TDesC& aDbName)
|
sl@0
|
1207 |
{
|
sl@0
|
1208 |
__ASSERT_DEBUG(!aFileData.IsReadOnly(), __SQLPANIC(ESqlPanicInternalError));
|
sl@0
|
1209 |
#if !defined(__SQL_DISABLE_SYMBIAN_SETTINGS_TABLE__)
|
sl@0
|
1210 |
//Make the journal file persistent - done by SQLite automatically because the locking mode is EXCLUSIVE
|
sl@0
|
1211 |
//__SQLLEAVE_IF_ERROR(::ExecPragma(iDbHandle, iAuthorizerDisabled, KPersistentJournalPragma, KPersist, aDbName));
|
sl@0
|
1212 |
//Load the current settings
|
sl@0
|
1213 |
TFileName storedCollationDllName;
|
sl@0
|
1214 |
TInt storedDbConfigFileVer = -1;
|
sl@0
|
1215 |
TInt currVacuumMode = -1;
|
sl@0
|
1216 |
__SQLLEAVE_IF_ERROR(::DbVacuumMode(iDbHandle, aDbName, currVacuumMode));
|
sl@0
|
1217 |
//currVacuumMode == ESqliteVacuumOff ==> This is a database created not by the SQL server
|
sl@0
|
1218 |
TSqlCompactionMode compactionMode = currVacuumMode == ESqliteVacuumOff ? ESqlCompactionManual : ESqlCompactionNotSet;
|
sl@0
|
1219 |
TSqlDbSysSettings dbSettings(iDbHandle);
|
sl@0
|
1220 |
dbSettings.LoadSettingsL(aDbName, storedCollationDllName, storedDbConfigFileVer, compactionMode);
|
sl@0
|
1221 |
if(currVacuumMode == ESqliteVacuumOff && compactionMode != ESqlCompactionManual)
|
sl@0
|
1222 |
{//The database has been opened and the vacuum mode is "off". Then this is a database, not created by SQL
|
sl@0
|
1223 |
//server or it is a corrupted database. The compaction mode read from the system table does not match the
|
sl@0
|
1224 |
//database vacuum mode. Conclusion: this is a corrupted database.
|
sl@0
|
1225 |
__SQLLEAVE(KErrCorrupt);
|
sl@0
|
1226 |
}
|
sl@0
|
1227 |
if(aFileData.ContainHandles() && aFileData.IsCreated())
|
sl@0
|
1228 |
{
|
sl@0
|
1229 |
compactionMode = aFileData.ConfigParams().iCompactionMode;
|
sl@0
|
1230 |
if(compactionMode == ESqlCompactionNotSet)
|
sl@0
|
1231 |
{
|
sl@0
|
1232 |
compactionMode = KSqlDefaultCompactionMode;
|
sl@0
|
1233 |
}
|
sl@0
|
1234 |
//This is a just created private database. Store the compaction mode (the compaction mode may have been set using a config string).
|
sl@0
|
1235 |
StoreSettingsL(storedCollationDllName, storedDbConfigFileVer, compactionMode);
|
sl@0
|
1236 |
}
|
sl@0
|
1237 |
//Init the database compaction mode
|
sl@0
|
1238 |
InitCompactionL(compactionMode, aFileData.ConfigParams().iFreePageThresholdKb, aFileData.FileName(),
|
sl@0
|
1239 |
(TSqliteVacuumMode)currVacuumMode, aDbName);
|
sl@0
|
1240 |
//Based on the current settings, apply any necessary configuration updates to the database
|
sl@0
|
1241 |
ApplyConfigUpdatesL(storedCollationDllName, storedDbConfigFileVer, aFileData, aDbName);
|
sl@0
|
1242 |
#endif // !(__SQL_DISABLE_SYMBIAN_SETTINGS_TABLE__)
|
sl@0
|
1243 |
}
|
sl@0
|
1244 |
|
sl@0
|
1245 |
/**
|
sl@0
|
1246 |
Applies any necessary configuration updates to the database, based on the current settings
|
sl@0
|
1247 |
in the settings table and how the database is being used (i.e. 'Opened' or 'Attached').
|
sl@0
|
1248 |
The applied configuration may include:
|
sl@0
|
1249 |
- Reindexing the main database and all attached databases, if the collation dll has been changed.
|
sl@0
|
1250 |
After the reindexation the new collation dll name will be stored in the settings table of the database.
|
sl@0
|
1251 |
- Executing all supported operations on the database that are specified in a database configuration
|
sl@0
|
1252 |
file, if such a file exists and has not already been processed.
|
sl@0
|
1253 |
The settings table will updated with the current version of the database configuration file if the file
|
sl@0
|
1254 |
is processed.
|
sl@0
|
1255 |
|
sl@0
|
1256 |
@param aStoredCollationDllName The name of the collation dll that is stored in the settings table,
|
sl@0
|
1257 |
@param aStoredDbConfigFileVersion The database configuration file version that is stored in the settings table,
|
sl@0
|
1258 |
@param aFileData The file data object,
|
sl@0
|
1259 |
@param aDbName Logical database name: "main" for the main database or attached database name,
|
sl@0
|
1260 |
|
sl@0
|
1261 |
@leave The function may leave with system-wide error codes or SQL errors of ESqlDbError type
|
sl@0
|
1262 |
*/
|
sl@0
|
1263 |
void CSqlSrvDatabase::ApplyConfigUpdatesL(const TDesC& aStoredCollationDllName, const TInt& aStoredDbConfigFileVersion,
|
sl@0
|
1264 |
const TSqlSrvFileData& aFileData, const TDesC& aDbName)
|
sl@0
|
1265 |
{
|
sl@0
|
1266 |
TSqlDbSysSettings dbSettings(iDbHandle);
|
sl@0
|
1267 |
//Check whether reindexing is necessary
|
sl@0
|
1268 |
if(::SqlServer().CollationDllName().CompareF(aStoredCollationDllName) != 0)
|
sl@0
|
1269 |
{
|
sl@0
|
1270 |
SQL_TRACE_INTERNALS(OstTraceExt3(TRACE_INTERNALS, CSQLSRVDATABASE_APPLYCONFIGUPDATES2L, "0x%X;CSqlSrvDatabase::ApplyConfigUpdatesL;Reindex db;aStoredCollationDllName=%S;aDbName=%S", (TUint)this, __SQLPRNSTR(aStoredCollationDllName), __SQLPRNSTR(aDbName)));
|
sl@0
|
1271 |
dbSettings.ReindexDatabaseL(aDbName, ::SqlServer().CollationDllName());
|
sl@0
|
1272 |
}
|
sl@0
|
1273 |
|
sl@0
|
1274 |
//Perform any necessary configuration file updates to the database.
|
sl@0
|
1275 |
//We do not want failures here to cause the database to fail
|
sl@0
|
1276 |
//to be opened and so any leave error is TRAPed and ignored
|
sl@0
|
1277 |
//(the error is logged in _DEBUG mode)
|
sl@0
|
1278 |
TRAPD(err, dbSettings.ConfigureDatabaseL(aStoredDbConfigFileVersion, aFileData, aDbName));
|
sl@0
|
1279 |
if(KErrNone != err)
|
sl@0
|
1280 |
{
|
sl@0
|
1281 |
SQL_TRACE_INTERNALS(OstTraceExt2(TRACE_INTERNALS, CSQLSRVDATABASE_APPLYCONFIGUPDATESL, "0x%X;CSqlSrvDatabase::ApplyConfigUpdatesL;ConfigureDatabaseL() failed with error code %d", (TUint)this, err));
|
sl@0
|
1282 |
}
|
sl@0
|
1283 |
}
|
sl@0
|
1284 |
|
sl@0
|
1285 |
/**
|
sl@0
|
1286 |
Sets the "cache size" and "page size" parameter values, if their values are valid.
|
sl@0
|
1287 |
This is done formatting and executing PRAGMA statements.
|
sl@0
|
1288 |
@param aConfigParams This object contains the cofiguration parameters
|
sl@0
|
1289 |
@param aSetPageSize If true, the page size will be set, otherwise not.
|
sl@0
|
1290 |
The aSetPageSize is set to true if:
|
sl@0
|
1291 |
1) The operation is "create database"
|
sl@0
|
1292 |
2) The operation is "open private database"
|
sl@0
|
1293 |
@param aLogicalDbName Parameter with default value of KNullDesC. If aLogicalDbName length is not 0, then the
|
sl@0
|
1294 |
"cache_size" pragma will be executed on the attached database with aLogicalDbName name.
|
sl@0
|
1295 |
*/
|
sl@0
|
1296 |
void CSqlSrvDatabase::SetConfigL(const TSqlSrvConfigParams& aConfigParams, TBool aSetPageSize, const TDesC& aLogicalDbName)
|
sl@0
|
1297 |
{
|
sl@0
|
1298 |
__ASSERT_DEBUG(aConfigParams.iPageSize == TSqlSrvConfigParams::KConfigPrmValueNotSet || aConfigParams.iPageSize >= 0, __SQLPANIC(ESqlPanicBadArgument));
|
sl@0
|
1299 |
__ASSERT_DEBUG(aConfigParams.iCacheSize == TSqlSrvConfigParams::KConfigPrmValueNotSet || aConfigParams.iCacheSize >= 0, __SQLPANIC(ESqlPanicBadArgument));
|
sl@0
|
1300 |
if(aSetPageSize && aConfigParams.iPageSize != TSqlSrvConfigParams::KConfigPrmValueNotSet)
|
sl@0
|
1301 |
{
|
sl@0
|
1302 |
__SQLLEAVE_IF_ERROR(::ExecPragma(iDbHandle, iAuthorizerDisabled, KPageSizePragma, aConfigParams.iPageSize));
|
sl@0
|
1303 |
}
|
sl@0
|
1304 |
|
sl@0
|
1305 |
const TDesC& logicalDbName = aLogicalDbName.Length() > 0 ? aLogicalDbName : KMainDb16;
|
sl@0
|
1306 |
|
sl@0
|
1307 |
::SetJournalSizeLimitL(iDbHandle, iAuthorizerDisabled, aConfigParams.iPageSize, logicalDbName);
|
sl@0
|
1308 |
|
sl@0
|
1309 |
//Setting the cache size.
|
sl@0
|
1310 |
//Step 1: Check if aConfigParams.iCacheSize value is set. If it is set, then use it.
|
sl@0
|
1311 |
if(aConfigParams.iCacheSize != TSqlSrvConfigParams::KConfigPrmValueNotSet)
|
sl@0
|
1312 |
{
|
sl@0
|
1313 |
__SQLLEAVE_IF_ERROR(::ExecPragma(iDbHandle, iAuthorizerDisabled, KCacheSizePragma, aConfigParams.iCacheSize, logicalDbName));
|
sl@0
|
1314 |
}
|
sl@0
|
1315 |
else
|
sl@0
|
1316 |
{
|
sl@0
|
1317 |
//Step 2: aConfigParams.iCacheSize value is not set. Then check if aConfigParams.iSoftHeapLimitKb value is set.
|
sl@0
|
1318 |
if(aConfigParams.iSoftHeapLimitKb != TSqlSrvConfigParams::KConfigPrmValueNotSet)
|
sl@0
|
1319 |
{
|
sl@0
|
1320 |
__ASSERT_DEBUG(aConfigParams.iSoftHeapLimitKb >= TSqlSrvConfigParams::KMinSoftHeapLimitKb &&
|
sl@0
|
1321 |
aConfigParams.iSoftHeapLimitKb <= TSqlSrvConfigParams::KMaxSoftHeapLimitKb, __SQLPANIC(ESqlPanicInternalError));
|
sl@0
|
1322 |
//Step 3: aConfigParams.iSoftHeapLimitKb value is set. Then use it to calculate the cache size. But we need the page size first.
|
sl@0
|
1323 |
// aLogicalDbName is used instead of logicalDbName because PageSizeL() if called with non-zero length name,
|
sl@0
|
1324 |
// "thinks" it is the main database name. KMainDb16 will be interpreted as an attached database name.
|
sl@0
|
1325 |
TInt pageSize = PageSizeL(aLogicalDbName);
|
sl@0
|
1326 |
//Step 4: Calculate the cache size.
|
sl@0
|
1327 |
TInt cacheSize = ((TInt64)aConfigParams.iSoftHeapLimitKb * 1024) / pageSize;//"TInt64" cast is used because of a possible overflow
|
sl@0
|
1328 |
//Step 5: Set the cache size.
|
sl@0
|
1329 |
__SQLLEAVE_IF_ERROR(::ExecPragma(iDbHandle, iAuthorizerDisabled, KCacheSizePragma, cacheSize, logicalDbName));
|
sl@0
|
1330 |
}
|
sl@0
|
1331 |
}
|
sl@0
|
1332 |
}
|
sl@0
|
1333 |
|
sl@0
|
1334 |
/**
|
sl@0
|
1335 |
Initializes the database compaction mode.
|
sl@0
|
1336 |
If the aCompactionMode parameter is ESqlCompactionBackground, the database with aDbFileName file name will be added
|
sl@0
|
1337 |
to the compactor for background compacting.
|
sl@0
|
1338 |
|
sl@0
|
1339 |
@param aCompactionMode The database compaction mode. See TSqlCompactionMode enum for the supported database compaction modes.
|
sl@0
|
1340 |
@param aFreePageThresholdKb Free page threshold. The background compaction won't start if the free pages size in Kb is less than
|
sl@0
|
1341 |
the free page threshold.
|
sl@0
|
1342 |
@param aDbFileName Database file name including full path
|
sl@0
|
1343 |
@param aCurrentVacuumMode The current SQLite vacuum mode, one of TSqliteVacuumMode enum item values.
|
sl@0
|
1344 |
If the current database vacuum mode is ESqliteVacuumOff, which means
|
sl@0
|
1345 |
the database has been created not by the SQL server,
|
sl@0
|
1346 |
then the "off" vacuum mode is kept unchanged.
|
sl@0
|
1347 |
@param aDbName "main" or the attached database name
|
sl@0
|
1348 |
|
sl@0
|
1349 |
@leave KErrNoMemory, an out of memory condition has occurred;
|
sl@0
|
1350 |
Note that the function may also leave with some other database specific
|
sl@0
|
1351 |
errors categorised as ESqlDbError, and other system-wide error codes.
|
sl@0
|
1352 |
|
sl@0
|
1353 |
@see TSqlCompactionMode
|
sl@0
|
1354 |
@see CSqlCompactor
|
sl@0
|
1355 |
@see TSqliteVacuumMode
|
sl@0
|
1356 |
|
sl@0
|
1357 |
@panic SqlDb 4 In _DEBUG mode if aCompactionMode parameter value is invalid.
|
sl@0
|
1358 |
*/
|
sl@0
|
1359 |
void CSqlSrvDatabase::InitCompactionL(TSqlCompactionMode aCompactionMode, TInt aFreePageThresholdKb,
|
sl@0
|
1360 |
const TDesC& aDbFileName, TSqliteVacuumMode aCurrentVacuumMode, const TDesC& aDbName)
|
sl@0
|
1361 |
{
|
sl@0
|
1362 |
__ASSERT_DEBUG(aCompactionMode == ESqlCompactionManual || aCompactionMode == ESqlCompactionBackground || aCompactionMode == ESqlCompactionAuto, __SQLPANIC(ESqlPanicBadArgument));
|
sl@0
|
1363 |
__ASSERT_DEBUG(aCurrentVacuumMode == ESqliteVacuumOff || aCurrentVacuumMode == ESqliteVacuumAuto ||
|
sl@0
|
1364 |
aCurrentVacuumMode == ESqliteVacuumIncremental, __SQLPANIC(ESqlPanicBadArgument));
|
sl@0
|
1365 |
__ASSERT_DEBUG(aFreePageThresholdKb >= 0, __SQLPANIC(ESqlPanicBadArgument));
|
sl@0
|
1366 |
TSqliteVacuumMode newSqliteVacuumMode = aCompactionMode == ESqlCompactionAuto ? ESqliteVacuumAuto : ESqliteVacuumIncremental;
|
sl@0
|
1367 |
if(aCurrentVacuumMode == ESqliteVacuumOff)
|
sl@0
|
1368 |
{
|
sl@0
|
1369 |
newSqliteVacuumMode = ESqliteVacuumOff;
|
sl@0
|
1370 |
}
|
sl@0
|
1371 |
if(aCurrentVacuumMode != newSqliteVacuumMode)
|
sl@0
|
1372 |
{
|
sl@0
|
1373 |
__SQLLEAVE_IF_ERROR(::ExecPragma(iDbHandle, iAuthorizerDisabled, KAutoVacuumPragma, newSqliteVacuumMode, aDbName));
|
sl@0
|
1374 |
}
|
sl@0
|
1375 |
if(aCompactionMode == ESqlCompactionBackground)
|
sl@0
|
1376 |
{
|
sl@0
|
1377 |
NewCompactEntryL(aFreePageThresholdKb, aDbFileName, aDbName);
|
sl@0
|
1378 |
}
|
sl@0
|
1379 |
}
|
sl@0
|
1380 |
|
sl@0
|
1381 |
/**
|
sl@0
|
1382 |
Adds the aDbFileName database to the compactor object for background compacting.
|
sl@0
|
1383 |
|
sl@0
|
1384 |
@param aFreePageThresholdKb Free page threshold in Kb. The background compaction won't start if the total size of the free pages
|
sl@0
|
1385 |
is less than the free page threshold.
|
sl@0
|
1386 |
@param aDbFileName Database file name including full path
|
sl@0
|
1387 |
@param aDbName "main" or the attached database name
|
sl@0
|
1388 |
|
sl@0
|
1389 |
@leave KErrNoMemory, an out of memory condition has occurred;
|
sl@0
|
1390 |
Note that the function may also leave with some other database specific
|
sl@0
|
1391 |
errors categorised as ESqlDbError, and other system-wide error codes.
|
sl@0
|
1392 |
|
sl@0
|
1393 |
@see CSqlCompactor
|
sl@0
|
1394 |
@see RSqlCompactDbMap
|
sl@0
|
1395 |
*/
|
sl@0
|
1396 |
void CSqlSrvDatabase::NewCompactEntryL(TInt aFreePageThresholdKb, const TDesC& aDbFileName, const TDesC& aDbName)
|
sl@0
|
1397 |
{
|
sl@0
|
1398 |
SQL_TRACE_INTERNALS(OstTraceExt4(TRACE_INTERNALS, CSQLSRVDATABASE_NEWCOMPACTENTRYL_ENTRY, "Entry;0x%X;CSqlSrvDatabase::NewCompactEntryL;aFreePageThresholdKb=%d;aDbFileName=%S;aDbName=%S", (TUint)this, aFreePageThresholdKb, __SQLPRNSTR(aDbFileName), __SQLPRNSTR(aDbName)));
|
sl@0
|
1399 |
TSqlCompactSettings settings;
|
sl@0
|
1400 |
settings.iFreePageThresholdKb = aFreePageThresholdKb;
|
sl@0
|
1401 |
::SqlServer().Compactor().AddEntryL(aDbFileName, settings);
|
sl@0
|
1402 |
TInt err = KErrNoMemory;
|
sl@0
|
1403 |
HBufC* key = aDbName.Alloc();
|
sl@0
|
1404 |
HBufC* data = aDbFileName.Alloc();
|
sl@0
|
1405 |
if(key && data)
|
sl@0
|
1406 |
{
|
sl@0
|
1407 |
__ASSERT_DEBUG(!iCompactDbMap.Entry(key), __SQLPANIC(ESqlPanicObjExists));
|
sl@0
|
1408 |
err = iCompactDbMap.Insert(key, data);//returns the index of the new entry
|
sl@0
|
1409 |
}
|
sl@0
|
1410 |
if(err < 0) //If either "key" or "data" or both is NULL, then "err" is KErrNoMemory and the next "if" will be executed.
|
sl@0
|
1411 |
{
|
sl@0
|
1412 |
delete data;
|
sl@0
|
1413 |
delete key;
|
sl@0
|
1414 |
::SqlServer().Compactor().ReleaseEntry(aDbFileName);
|
sl@0
|
1415 |
}
|
sl@0
|
1416 |
SQL_TRACE_INTERNALS(OstTraceExt2(TRACE_INTERNALS, CSQLSRVDATABASE_NEWCOMPACTENTRYL_EXIT, "Exit;0x%X;CSqlSrvDatabase::NewCompactEntryL;err=%d", (TUint)this, err));
|
sl@0
|
1417 |
__SQLLEAVE_IF_ERROR(err);
|
sl@0
|
1418 |
}
|
sl@0
|
1419 |
|
sl@0
|
1420 |
/**
|
sl@0
|
1421 |
Removes database (identified by its logical name) from the compactor.
|
sl@0
|
1422 |
|
sl@0
|
1423 |
@param aDbName "main" or the attached database name
|
sl@0
|
1424 |
|
sl@0
|
1425 |
@see CSqlCompactor
|
sl@0
|
1426 |
@see RSqlCompactDbMap
|
sl@0
|
1427 |
*/
|
sl@0
|
1428 |
void CSqlSrvDatabase::ReleaseCompactEntry(const TDesC& aDbName)
|
sl@0
|
1429 |
{
|
sl@0
|
1430 |
TSqlCompactDbMapIterator compactDbIt(iCompactDbMap);
|
sl@0
|
1431 |
TSqlCompactDbPair compactDbPair;
|
sl@0
|
1432 |
while(compactDbIt.Next(compactDbPair))
|
sl@0
|
1433 |
{
|
sl@0
|
1434 |
if(::CompareNoCase(*compactDbPair.iKey, aDbName) == 0)
|
sl@0
|
1435 |
{
|
sl@0
|
1436 |
::SqlServer().Compactor().ReleaseEntry(*compactDbPair.iData);
|
sl@0
|
1437 |
iCompactDbMap.Remove(compactDbPair.iKey);
|
sl@0
|
1438 |
SQL_TRACE_INTERNALS(OstTrace1(TRACE_INTERNALS, CSQLSRVDATABASE_RELEASECOMPACTENTRY, "0x%X;CSqlSrvDatabase::ReleaseCompactEntry", (TUint)this));
|
sl@0
|
1439 |
break;
|
sl@0
|
1440 |
}
|
sl@0
|
1441 |
}
|
sl@0
|
1442 |
}
|
sl@0
|
1443 |
|
sl@0
|
1444 |
/**
|
sl@0
|
1445 |
Cleanup function.
|
sl@0
|
1446 |
Used during the construction phase of the CSqlSrvDatabase instance when a new database is created.
|
sl@0
|
1447 |
If the database creation succeeds, the "init compaction" operation succeeds but some other init operation fail,
|
sl@0
|
1448 |
the just created database file has to be deleted. But before that the database has to be removed from the compactor,
|
sl@0
|
1449 |
because the compactor creates independent database connection that has to be closed before the database deletion.
|
sl@0
|
1450 |
|
sl@0
|
1451 |
The database will be removed from the compactor as a result of the call.
|
sl@0
|
1452 |
|
sl@0
|
1453 |
@param aCleanup A pointer to the CSqlSrvDatabase object
|
sl@0
|
1454 |
*/
|
sl@0
|
1455 |
void CSqlSrvDatabase::CompactCleanup(void* aCleanup)
|
sl@0
|
1456 |
{
|
sl@0
|
1457 |
CSqlSrvDatabase* self = reinterpret_cast <CSqlSrvDatabase*> (aCleanup);
|
sl@0
|
1458 |
__ASSERT_DEBUG(self != NULL, __SQLPANIC2(ESqlPanicBadArgument));
|
sl@0
|
1459 |
self->ReleaseCompactEntry(KMainDb16);
|
sl@0
|
1460 |
}
|
sl@0
|
1461 |
|
sl@0
|
1462 |
/**
|
sl@0
|
1463 |
Retrieves the database page size.
|
sl@0
|
1464 |
If the request is for the main database page size and if the size is not retrieved yet, then the page size value will be
|
sl@0
|
1465 |
cached in iPageSize data member.
|
sl@0
|
1466 |
|
sl@0
|
1467 |
@param aDbName Attached database name or KNullDesC for the main database
|
sl@0
|
1468 |
|
sl@0
|
1469 |
@leave KErrNoMemory, an out of memory condition has occurred;
|
sl@0
|
1470 |
Note that the function may also leave with some other database specific
|
sl@0
|
1471 |
errors categorised as ESqlDbError, and other system-wide error codes.
|
sl@0
|
1472 |
|
sl@0
|
1473 |
@return The database page size
|
sl@0
|
1474 |
*/
|
sl@0
|
1475 |
TInt CSqlSrvDatabase::PageSizeL(const TDesC& aDbName)
|
sl@0
|
1476 |
{
|
sl@0
|
1477 |
if(iPageSize > 0 && aDbName == KNullDesC)
|
sl@0
|
1478 |
{
|
sl@0
|
1479 |
return iPageSize;
|
sl@0
|
1480 |
}
|
sl@0
|
1481 |
iAuthorizerDisabled = ETrue;
|
sl@0
|
1482 |
CleanupStack::PushL(TCleanupItem(&EnableAuthorizer, &iAuthorizerDisabled));
|
sl@0
|
1483 |
TInt pageSize = 0;
|
sl@0
|
1484 |
__SQLLEAVE_IF_ERROR(::DbPageSize(iDbHandle, aDbName, pageSize));
|
sl@0
|
1485 |
CleanupStack::PopAndDestroy();
|
sl@0
|
1486 |
__ASSERT_DEBUG(pageSize > 0, __SQLPANIC(ESqlPanicInternalError));
|
sl@0
|
1487 |
if(aDbName == KNullDesC)
|
sl@0
|
1488 |
{
|
sl@0
|
1489 |
iPageSize = pageSize;
|
sl@0
|
1490 |
}
|
sl@0
|
1491 |
return pageSize;
|
sl@0
|
1492 |
}
|
sl@0
|
1493 |
|
sl@0
|
1494 |
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
sl@0
|
1495 |
///////////////////////////// ConstructL() methods ///////////////////////////////////////
|
sl@0
|
1496 |
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
sl@0
|
1497 |
|
sl@0
|
1498 |
/**
|
sl@0
|
1499 |
Second phase construction method. Creates a new secure database file.
|
sl@0
|
1500 |
If the function fails, the database file will be closed and deleted.
|
sl@0
|
1501 |
|
sl@0
|
1502 |
@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
|
sl@0
|
1503 |
file session reference and some other database file related properties.
|
sl@0
|
1504 |
If this is a secure database, then the format of the name must be:
|
sl@0
|
1505 |
\<drive\>:\<[SID]database file name excluding the path\>.
|
sl@0
|
1506 |
If this is a non-secure database, then the file name has to be the full database file name.
|
sl@0
|
1507 |
"[SID]" refers to SID of the application which creates the database.
|
sl@0
|
1508 |
@param aSecurityPolicy Database security policy
|
sl@0
|
1509 |
|
sl@0
|
1510 |
@panic SqlDb 4 In _DEBUG mode if aSecurityPolicy is NULL.
|
sl@0
|
1511 |
*/
|
sl@0
|
1512 |
void CSqlSrvDatabase::ConstructCreateSecureL(const TSqlSrvFileData& aFileData, CSqlSecurityPolicy* aSecurityPolicy)
|
sl@0
|
1513 |
{
|
sl@0
|
1514 |
__ASSERT_DEBUG(aSecurityPolicy != NULL, __SQLPANIC(ESqlPanicBadArgument));
|
sl@0
|
1515 |
//Insert a new item in the security policies map.
|
sl@0
|
1516 |
CleanupStack::PushL(aSecurityPolicy);
|
sl@0
|
1517 |
const TUint8* mapKey = SecurityMapKeyL(aFileData.FileName());
|
sl@0
|
1518 |
mapKey = ::CreateStrCopyLC(mapKey);
|
sl@0
|
1519 |
__ASSERT_DEBUG(!::SqlServer().SecurityMap().Entry(mapKey), __SQLPANIC(ESqlPanicObjExists));
|
sl@0
|
1520 |
__SQLLEAVE_IF_ERROR(::SqlServer().SecurityMap().Insert(mapKey, aSecurityPolicy));
|
sl@0
|
1521 |
CleanupStack::Pop(2);//iSecurityMap owns mapKey and aSecurityPolicy.
|
sl@0
|
1522 |
iSecureDbName = mapKey;
|
sl@0
|
1523 |
iSecurityPolicy = aSecurityPolicy;
|
sl@0
|
1524 |
//
|
sl@0
|
1525 |
DoCommonConstructCreateL(aFileData, ETrue);
|
sl@0
|
1526 |
}
|
sl@0
|
1527 |
|
sl@0
|
1528 |
/**
|
sl@0
|
1529 |
Second phase construction method. Creates a new non-secure database file.
|
sl@0
|
1530 |
If the function fails, the database file will be closed and deleted.
|
sl@0
|
1531 |
|
sl@0
|
1532 |
@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
|
sl@0
|
1533 |
file session reference and some other database file related properties.
|
sl@0
|
1534 |
If this is a secure database, then the format of the name must be:
|
sl@0
|
1535 |
\<drive\>:\<[SID]database file name excluding the path\>.
|
sl@0
|
1536 |
If this is a non-secure database, then the file name has to be the full database file name.
|
sl@0
|
1537 |
"[SID]" refers to SID of the application which creates the database.
|
sl@0
|
1538 |
*/
|
sl@0
|
1539 |
void CSqlSrvDatabase::ConstructCreateL(const TSqlSrvFileData& aFileData)
|
sl@0
|
1540 |
{
|
sl@0
|
1541 |
DoCommonConstructCreateL(aFileData, EFalse);
|
sl@0
|
1542 |
}
|
sl@0
|
1543 |
|
sl@0
|
1544 |
//Called by the two "Contruct&Create" methods: ConstructCreateL() and ConstructCreateSecureL().
|
sl@0
|
1545 |
//The aSecureDb parameter tells which method is the caller.
|
sl@0
|
1546 |
//The function performs common construction and initialization:
|
sl@0
|
1547 |
// - creates the database file
|
sl@0
|
1548 |
// - makes the journal file persistent
|
sl@0
|
1549 |
// - initializes the database compaction mode
|
sl@0
|
1550 |
// - stores the initial settings in the settings table, including the current collation dll name
|
sl@0
|
1551 |
// - stores the security settings and installs the authorizer, if aSecureDb is true
|
sl@0
|
1552 |
// - installs the user-defined functions
|
sl@0
|
1553 |
// - installs collations
|
sl@0
|
1554 |
//If the method fails and the error is not KErrAlreadyExists, the database file will be closed and deleted.
|
sl@0
|
1555 |
void CSqlSrvDatabase::DoCommonConstructCreateL(const TSqlSrvFileData& aFileData, TBool aSecureDb)
|
sl@0
|
1556 |
{
|
sl@0
|
1557 |
__ASSERT_DEBUG(!iDbHandle, __SQLPANIC(ESqlPanicInternalError));
|
sl@0
|
1558 |
__ASSERT_DEBUG(aSecureDb ? iSecurityPolicy != NULL : ETrue, __SQLPANIC(ESqlPanicInternalError));
|
sl@0
|
1559 |
CreateNewDbFileL(aFileData);
|
sl@0
|
1560 |
TDbFileCleanup dbFileCleanup(aFileData, iDbHandle);
|
sl@0
|
1561 |
CleanupStack::PushL(TCleanupItem(&DbFileCleanup, &dbFileCleanup));
|
sl@0
|
1562 |
//Make the journal file persistent - done by SQLite automatically because the locking mode is EXCLUSIVE
|
sl@0
|
1563 |
//::ExecPragma(iDbHandle, iAuthorizerDisabled, KPersistentJournalPragma, KPersist);
|
sl@0
|
1564 |
//Init database compaction mode
|
sl@0
|
1565 |
TSqlCompactionMode compactionMode = aFileData.ConfigParams().iCompactionMode;
|
sl@0
|
1566 |
if(compactionMode == ESqlCompactionNotSet)
|
sl@0
|
1567 |
{
|
sl@0
|
1568 |
compactionMode = KSqlDefaultCompactionMode;
|
sl@0
|
1569 |
}
|
sl@0
|
1570 |
TInt currVacuumMode = -1;
|
sl@0
|
1571 |
__SQLLEAVE_IF_ERROR(::DbVacuumMode(iDbHandle, KNullDesC, currVacuumMode));
|
sl@0
|
1572 |
//currVacuumMode == ESqliteVacuumOff ==> This is a database created not by the SQL server
|
sl@0
|
1573 |
InitCompactionL(compactionMode, aFileData.ConfigParams().iFreePageThresholdKb, aFileData.FileName(), (TSqliteVacuumMode)currVacuumMode);
|
sl@0
|
1574 |
CleanupStack::PushL(TCleanupItem(&CSqlSrvDatabase::CompactCleanup, this));
|
sl@0
|
1575 |
//Store the initial settings in the settings table (including the current collation dll name)
|
sl@0
|
1576 |
StoreSettingsL(::SqlServer().CollationDllName(), KSqlNullDbConfigFileVersion, compactionMode);
|
sl@0
|
1577 |
if(aSecureDb)
|
sl@0
|
1578 |
{
|
sl@0
|
1579 |
//Store the security policies in the security policies tables.
|
sl@0
|
1580 |
TSqlDbSysSettings dbSysSettings(iDbHandle);
|
sl@0
|
1581 |
dbSysSettings.StoreSecurityPolicyL(*iSecurityPolicy);
|
sl@0
|
1582 |
}
|
sl@0
|
1583 |
InstallAuthorizerL();
|
sl@0
|
1584 |
InstallUDFsL();
|
sl@0
|
1585 |
InstallCollationsL();
|
sl@0
|
1586 |
CleanupStack::Pop(2);//CompactCleanup, DbFileCleanup
|
sl@0
|
1587 |
SQLPROFILER_DB_CREATE((TUint)iDbHandle, aFileData.FileName());
|
sl@0
|
1588 |
}
|
sl@0
|
1589 |
|
sl@0
|
1590 |
/**
|
sl@0
|
1591 |
Second phase construction method. Opens an existing secure database file.
|
sl@0
|
1592 |
|
sl@0
|
1593 |
@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
|
sl@0
|
1594 |
file session reference and some other database file related properties.
|
sl@0
|
1595 |
If this is a secure database, then the format of the name must be:
|
sl@0
|
1596 |
\<drive\>:\<[SID]database file name excluding the path\>.
|
sl@0
|
1597 |
If this is a non-secure database, then the file name has to be the full database file name.
|
sl@0
|
1598 |
"[SID]" refers to SID of the application which creates the database.
|
sl@0
|
1599 |
*/
|
sl@0
|
1600 |
void CSqlSrvDatabase::ConstructOpenSecureL(const TSqlSrvFileData& aFileData)
|
sl@0
|
1601 |
{
|
sl@0
|
1602 |
DoCommonConstructOpenL(aFileData, ETrue);
|
sl@0
|
1603 |
}
|
sl@0
|
1604 |
|
sl@0
|
1605 |
/**
|
sl@0
|
1606 |
Second phase construction method. Opens an existing non-secure database file.
|
sl@0
|
1607 |
|
sl@0
|
1608 |
@param aFileData A reference to a TSqlSrvFileData instance, which keeps the database name, a
|
sl@0
|
1609 |
file session reference and some other database file related properties.
|
sl@0
|
1610 |
If this is a secure database, then the format of the name must be:
|
sl@0
|
1611 |
\<drive\>:\<[SID]database file name excluding the path\>.
|
sl@0
|
1612 |
If this is a non-secure database, then the file name has to be the full database file name.
|
sl@0
|
1613 |
"[SID]" refers to SID of the application which creates the database.
|
sl@0
|
1614 |
If this is application's private database, then the format of aFileData is as it is described
|
sl@0
|
1615 |
in TSqlSrvFileData::SetFromHandleL() comments.
|
sl@0
|
1616 |
@see TSqlSrvFileData::SetFromHandleL()
|
sl@0
|
1617 |
*/
|
sl@0
|
1618 |
void CSqlSrvDatabase::ConstructOpenL(const TSqlSrvFileData& aFileData)
|
sl@0
|
1619 |
{
|
sl@0
|
1620 |
DoCommonConstructOpenL(aFileData, EFalse);
|
sl@0
|
1621 |
}
|
sl@0
|
1622 |
|
sl@0
|
1623 |
//Opens a database and does all necessary initializations
|
sl@0
|
1624 |
//Called by the two "Contruct&Open" methods: ConstructOpenL() and ConstructOpenSecureL().
|
sl@0
|
1625 |
//The aSecureDb parameter tells which method is the caller.
|
sl@0
|
1626 |
//The function performs common construction and initialization:
|
sl@0
|
1627 |
// - opens the database file
|
sl@0
|
1628 |
// - installs the user-defined functions
|
sl@0
|
1629 |
// - installs collations
|
sl@0
|
1630 |
// - installs the authoriser callback
|
sl@0
|
1631 |
void CSqlSrvDatabase::DoCommonConstructOpenL(const TSqlSrvFileData& aFileData, TBool aSecureDb)
|
sl@0
|
1632 |
{
|
sl@0
|
1633 |
OpenExistingDbFileL(aFileData);//iDbHandle is valid after a successful call
|
sl@0
|
1634 |
//The user-defined collations must be installed before the possible database reindexing!!!
|
sl@0
|
1635 |
InstallCollationsL();
|
sl@0
|
1636 |
if(!aFileData.IsReadOnly())
|
sl@0
|
1637 |
{//No need to disable the authorizer since it is not installed yet.
|
sl@0
|
1638 |
//Make sure that the user-defined collation have been installed before the reindexing operation.
|
sl@0
|
1639 |
ProcessSettingsL(aFileData, KMainDb16);
|
sl@0
|
1640 |
}
|
sl@0
|
1641 |
if(aSecureDb)
|
sl@0
|
1642 |
{
|
sl@0
|
1643 |
const TUint8* mapKey = NULL;
|
sl@0
|
1644 |
//Load database security policy, update the security policy map
|
sl@0
|
1645 |
UpdateSecurityMapL(EFalse, aFileData, mapKey, iSecurityPolicy);
|
sl@0
|
1646 |
iSecureDbName = mapKey;//used in CSqlSrvDatabase destructor.
|
sl@0
|
1647 |
mapKey = NULL;//it is not used
|
sl@0
|
1648 |
//Check that the caller has at least one of {Schema, Read, Write} policies.
|
sl@0
|
1649 |
BasicSecurityPolicyCheckL(*iSecurityPolicy);
|
sl@0
|
1650 |
}
|
sl@0
|
1651 |
//Install user-defined functions.
|
sl@0
|
1652 |
InstallUDFsL();
|
sl@0
|
1653 |
|
sl@0
|
1654 |
//Install the authorizer.
|
sl@0
|
1655 |
InstallAuthorizerL();
|
sl@0
|
1656 |
|
sl@0
|
1657 |
SQLPROFILER_DB_OPEN((TUint)iDbHandle, aFileData.FileName());
|
sl@0
|
1658 |
}
|
sl@0
|
1659 |
|
sl@0
|
1660 |
/*
|
sl@0
|
1661 |
Implementation of the like() SQL function. This function implements
|
sl@0
|
1662 |
the user defined LIKE operator. The first argument to the function is the
|
sl@0
|
1663 |
pattern and the second argument is the string. So, the SQL statements:
|
sl@0
|
1664 |
A LIKE B
|
sl@0
|
1665 |
is implemented as like(B, A).
|
sl@0
|
1666 |
|
sl@0
|
1667 |
@param aContext Function call context;
|
sl@0
|
1668 |
@param aArgc Number of LIKE arguments: 2 for the standard LIKE operator, 3 for the LIKE operator with an ESCAPE clause;
|
sl@0
|
1669 |
@param aArgv LIKE arguments;
|
sl@0
|
1670 |
|
sl@0
|
1671 |
@internalComponent
|
sl@0
|
1672 |
*/
|
sl@0
|
1673 |
void CSqlSrvDatabase::LikeSqlFunc(sqlite3_context* aContext, int aArgc, sqlite3_value** aArgv)
|
sl@0
|
1674 |
{
|
sl@0
|
1675 |
TUint escapeChar = 0;
|
sl@0
|
1676 |
if(aArgc == 3)
|
sl@0
|
1677 |
{
|
sl@0
|
1678 |
//The escape character string must consist of a single UTF16 character.
|
sl@0
|
1679 |
//Otherwise, return an error.
|
sl@0
|
1680 |
const TUint16* esc = static_cast <const TUint16*> (sqlite3_value_text16(aArgv[2]));
|
sl@0
|
1681 |
if(!esc)
|
sl@0
|
1682 |
{
|
sl@0
|
1683 |
sqlite3_result_error(aContext, KErrMsg1, -1);
|
sl@0
|
1684 |
return;
|
sl@0
|
1685 |
}
|
sl@0
|
1686 |
if(User::StringLength(esc) != 1)
|
sl@0
|
1687 |
{
|
sl@0
|
1688 |
sqlite3_result_error(aContext, KErrMsg2, -1);
|
sl@0
|
1689 |
return;
|
sl@0
|
1690 |
}
|
sl@0
|
1691 |
escapeChar = *esc;
|
sl@0
|
1692 |
}
|
sl@0
|
1693 |
const TUint16* pattern = static_cast <const TUint16*> (sqlite3_value_text16(aArgv[0]));
|
sl@0
|
1694 |
const TUint16* candidate = static_cast <const TUint16*> (sqlite3_value_text16(aArgv[1]));
|
sl@0
|
1695 |
if(pattern && candidate)
|
sl@0
|
1696 |
{
|
sl@0
|
1697 |
TInt wildChar = '_';
|
sl@0
|
1698 |
TInt wildSeqChar = '%';
|
sl@0
|
1699 |
TPtrC16 patternStr(pattern, (TUint)sqlite3_value_bytes16(aArgv[0]) / sizeof(TUint16));
|
sl@0
|
1700 |
TPtrC16 candidateStr(candidate, (TUint)sqlite3_value_bytes16(aArgv[1]) / sizeof(TUint16));
|
sl@0
|
1701 |
TInt res = candidateStr.MatchC(patternStr, wildChar, wildSeqChar, escapeChar, 0/*collation level*/);
|
sl@0
|
1702 |
sqlite3_result_int(aContext, res >= 0);
|
sl@0
|
1703 |
//RDebug::Print(_L("--res=%d, pattern=%S, candidate=%S\r\n"), res, &patternStr, &candidateStr);
|
sl@0
|
1704 |
}
|
sl@0
|
1705 |
}
|
sl@0
|
1706 |
|