Backout 128 limits in DataControl
[platform/framework/native/appfw.git] / src / io / FIo_DatabaseImpl.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file        FIo_DatabaseImpl.cpp
20  * @brief       This is the implementation file for _DatabaseImpl class.
21  */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <semaphore.h>
27 #include <fcntl.h>
28 #include <limits.h>
29 #include <errno.h>
30 #include <new>
31 #include <unique_ptr.h>
32 #include <sqlite3.h>
33 #include <dlfcn.h>
34
35 #include <FBaseResult.h>
36 #include <FBaseSysLog.h>
37 #include <FIoFile.h>
38 #include <FIoDirectory.h>
39 #include <FIoDbTypes.h>
40 #include <FIoDatabase.h>
41 #include <FIoDbStatement.h>
42 #include <FIoDbEnumerator.h>
43 #include <FSysSystemInfo.h>
44
45 #include <FBase_StringConverter.h>
46 #include <FBaseUtilStringUtil.h>
47 #include <FBase_NativeError.h>
48 #include <FApp_AppInfo.h>
49 #include <FIo_FileImpl.h>
50 #include <FIo_DatabaseImpl.h>
51 #include <FIo_DbStatementImpl.h>
52 #include <FIo_DbEnumeratorImpl.h>
53 #include <FIo_DbContextImpl.h>
54 #include <FIo_SecureIoUtil.h>
55 #include <FIo_IDbUserListener.h>
56
57 using namespace std;
58 using namespace Tizen::Base;
59 using namespace Tizen::App;
60 using namespace Tizen::Base::Runtime;
61 using namespace Tizen::Base::Utility;
62 using namespace Tizen::System;
63
64 namespace Tizen { namespace Io
65 {
66
67 // maximum argument count that can be passed to register user defined functions
68 const int MAX_FUNCTION_ARGUMENT_COUNT = 127;
69 const int MAX_UTF8_BYTES = 255;         // maximum length of UTF8 bytes
70 const int MAX_MUTEX_NAME_LENGTH = 32;   // maximum length of mutex name
71 const int MAX_DATABASE_AES_KEY_LENGTH = 16;     //default key size for AES 128
72 const int MAX_DATABASE_SQL_LENGTH = 4096;       //buffer length required to make sql query
73 const int MAX_SQLCIPHER_SCHEMA_PREFIX_SIZE = 13;//size of sqlCipher_ schema prefix name.
74
75 static const size_t _MAX_DB_OPENMODE_LENGTH = 2;
76 static const char _DATABASE_LIBRARY_PATH[] = "/usr/lib/libsqlite3.so.0";
77 static const char _DATABASE_ENCRYPTION_SYMBOL[] = "sqlite3_key";
78
79 _DatabaseImpl::_DatabaseImpl(void)
80         : __pDatabase(null)
81         , __transactionGoingOn(false)
82 {
83 }
84
85 _DatabaseImpl::~_DatabaseImpl(void)
86 {
87         result r = E_SUCCESS;
88         sqlite3_stmt* pSqlStmt = null;
89
90         if (__pDatabase)
91         {
92                 pSqlStmt = sqlite3_next_stmt((sqlite3*) __pDatabase, 0);
93                 while (pSqlStmt != null)
94                 {
95                         sqlite3_finalize(pSqlStmt);
96                         pSqlStmt = sqlite3_next_stmt((sqlite3*) __pDatabase, 0);
97                 }
98
99                 int ret = sqlite3_close((sqlite3*) __pDatabase);
100                 if (ret != SQLITE_OK)
101                 {
102                         r = __ConvertNativeSqliteErrorToResult(ret);
103                         SysLog(NID_IO, "[%s] ERROR Message: [%s], Failed to close database.", GetErrorMessage(r),
104                                                 sqlite3_errmsg((sqlite3*) __pDatabase));
105                 }
106                 else
107                 {
108                         __pDatabase = null;
109                         __transactionGoingOn = false;
110                 }
111         }
112
113         // release user context info
114         __userFunctionContextList.RemoveAll(true);
115         __userCollationContextList.RemoveAll(true);
116
117 }
118
119 bool
120 _DatabaseImpl::IsDirectory(const String& databasePath)
121 {
122         FileAttributes attr;
123         result r = E_SUCCESS;
124
125         SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(databasePath, _AppInfo::IsOspCompat()) == true,
126                         E_INVALID_ARG, " [%ls] is not compatible.", databasePath.GetPointer());
127
128         r = _FileImpl::GetAttributes(databasePath, attr);
129         if (IsFailed(r))
130         {
131                 SetLastResult(r);
132                 return false;
133         }
134
135         SetLastResult(E_SUCCESS);
136         return attr.IsDirectory();
137 }
138
139 bool
140 _DatabaseImpl::VerifyDatabaseOpenMode(const char* pOpenMode, long& legacyMode)
141 {
142         if (pOpenMode == null)
143         {
144                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode is null.");
145                 return false;
146         }
147
148         if (strlen(pOpenMode) > _MAX_DB_OPENMODE_LENGTH)
149         {
150                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
151                 return false;
152         }
153
154         if (pOpenMode[0] == 'r')
155         {
156                 if (pOpenMode[1] == '\0')
157                 {
158                         legacyMode = DB_OPEN_READ_ONLY;
159                 }
160                 else if (pOpenMode[1] == '+')
161                 {
162                         if (pOpenMode[2] == '\0')
163                         {
164                                 legacyMode = DB_OPEN_READ_WRITE;
165                         }
166                 }
167         }
168         else if (pOpenMode[0] == 'a' && pOpenMode[1] == '+' && pOpenMode[2] == '\0')
169         {
170                 legacyMode = (DB_OPEN_CREATE | DB_OPEN_READ_WRITE);
171         }
172         else
173         {
174                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
175                 return false;
176         }
177
178         return true;
179 }
180
181 result
182 _DatabaseImpl::Construct(const String& dbPath, bool createIfNotExist)
183 {
184         long openMode = DB_OPEN_READ_WRITE;
185
186         if (!_FileImpl::IsFileExist(dbPath))
187         {
188                 SysTryReturn(NID_IO, createIfNotExist == true, E_FILE_NOT_FOUND, E_FILE_NOT_FOUND,
189                                 "[E_FILE_NOT_FOUND] Database file does not exist. Create it first.");
190                 openMode = DB_OPEN_READ_WRITE | DB_OPEN_CREATE;
191         }
192
193         return Construct(dbPath, openMode, null);
194 }
195
196 result
197 _DatabaseImpl::Construct(const String& dbPath, long openMode, const ByteBuffer* pSecretKey)
198 {
199         SysAssertf(__pDatabase == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class\n");
200         SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(dbPath, _AppInfo::IsOspCompat()) == true,
201                         E_INVALID_ARG, " [%ls] is not compatible.", dbPath.GetPointer());
202         SysTryReturnResult(NID_IO, !(pSecretKey && pSecretKey->GetRemaining() <= 0), E_INVALID_ARG,
203                         "The specified secretKey is invalid.");
204
205         result r = E_SUCCESS;
206         int ret = 0;
207         int openFlags = 0;
208         sqlite3* pDb = null;
209         bool isFilePathExist = false;
210         bool isParentDirPathExist = false;
211         int lastIndex = -1;
212         String parentDirPath;
213
214         switch (openMode)
215         {
216         case (DB_OPEN_READ_WRITE):
217                 openFlags = SQLITE_OPEN_READWRITE;
218                 break;
219
220         case (DB_OPEN_READ_ONLY):
221                 openFlags = SQLITE_OPEN_READONLY;
222                 break;
223
224         case (DB_OPEN_READ_WRITE | DB_OPEN_CREATE):
225                 openFlags = (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
226                 break;
227
228         default:
229                 SysLog(NID_IO, "[E_INVALID_ARG] The specified open mode flags are invalid.");
230                 return E_INVALID_ARG;
231         }
232
233         // extract directory path from a given Db file path
234         // Find index of last occurrence  of character '/' in dbPath
235         r = dbPath.LastIndexOf(L'/', dbPath.GetLength() - 1, lastIndex);
236         SysTryReturnResult(NID_IO, !IsFailed(r),
237                 E_INVALID_ARG, "Missing directory path. SHOULD not happen.");
238
239         // extract directory path from dbPath starting from index 0 to lastIndex.
240         r = dbPath.SubString(0, lastIndex, parentDirPath);
241         SysTryReturnResult(NID_IO, !IsFailed(r),
242                 E_INVALID_ARG, "Missing directory path. SHOULD not happen.");
243
244         // TODO: Test sqlite3_open_v3() without parent directory.
245         //check existence of parent directory
246         isParentDirPathExist = _FileImpl::IsFileExist(String(parentDirPath));
247         SysTryReturnResult(NID_IO, isParentDirPathExist == true, E_INVALID_ARG,
248                            "Parent Directory does not exist.");
249
250         unique_ptr<char[]> pDbPath(_StringConverter::CopyToCharArrayN(dbPath));
251         r = GetLastResult();
252         SysTryCatch(NID_IO, pDbPath, , r, "[%s] pDbPath is null.", GetErrorMessage(r));
253
254         // check existence of file
255         isFilePathExist = _FileImpl::IsFileExist(dbPath);
256         if (isFilePathExist == true)
257         {
258                 if (openMode == (DB_OPEN_READ_WRITE | DB_OPEN_CREATE))
259                 {
260                         SysLog(NID_IO, "[E_FILE_ALREADY_EXIST] File already exists.");
261                         r = E_FILE_ALREADY_EXIST;
262                         goto CATCH;
263                 }
264
265                 //check if it is a directory
266                 if (IsDirectory(dbPath))
267                 {
268                         SysLog(NID_IO, "[E_DATABASE] Given path is not a File.");
269                         r = E_DATABASE;
270                         goto CATCH;
271                 }
272
273 #if 0
274                 _DatabaseMode dbMode = DATABASE_MODE_NONE;
275                 dbMode = _SecureIoUtil::GetDatabaseMode(pDbPath.get());
276                 SysTryCatch(NID_IO, dbMode != DATABASE_MODE_ERROR, r = E_IO, E_IO, "[E_IO] GetDatabaseMode function failed.");
277
278                 if (pSecretKey && _SecureIoUtil::IsNormalDatabase(dbMode))
279                 {
280                         SysTryCatch(NID_IO, false, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Trying to open a normal database in secure mode.");
281                 }
282                 else if (!pSecretKey && _SecureIoUtil::IsSecureDatabase(dbMode))
283                 {
284                         SysTryCatch(NID_IO, false, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Trying to open a secure database in normal mode.");
285                 }
286                 else
287                 {
288                         //Do Nothing
289                 }
290 #endif
291         }
292         else
293         {
294                 if (openMode == DB_OPEN_READ_WRITE || openMode == DB_OPEN_READ_ONLY)
295                 {
296                         SysLog(NID_IO, "[E_FILE_NOT_FOUND] File not found when opened in DB_OPEN_READ_WRITE/DB_OPEN_READ_ONLY mode.");
297                         r = E_FILE_NOT_FOUND;
298                         goto CATCH;
299                 }
300         }
301
302         // open/create the database
303         ret = sqlite3_open_v2(pDbPath.get(), &pDb, openFlags, null);
304         if (ret != SQLITE_OK)
305         {
306                 r = __ConvertNativeSqliteErrorToResult(ret);
307                 SysLog(NID_IO, "[%s] sqlite3_open_v2() failed (%d, %s).", GetErrorMessage(r), ret, sqlite3_errmsg(pDb));
308                 goto CATCH;
309         }
310
311         if (pSecretKey)
312         {
313                 unique_ptr<byte[]> pDbKey(_SecureIoUtil::GenerateDatabaseKeyN(pSecretKey));
314                 SysTryReturnResult(NID_IO, pDbKey != null, E_IO, "GenerateDatabaseKeyN returned null.");
315
316 #if 0
317                 bool secure = false;
318                 r = SystemInfo::GetValue(L"http://tizen.org/feature/database.encryption", secure);
319                 SysTryReturnResult(NID_IO, !IsFailed(r), E_SYSTEM, "The method cannot proceed due to a severe system error.");
320                 SysTryReturnResult(NID_IO, secure == true, E_UNSUPPORTED_OPERATION, "This operation is not supported.");
321
322                 ret = sqlite3_key(pDb, pDbKey.get(), MAX_DATABASE_AES_KEY_LENGTH * 2);
323 #else
324                 int (* sqlite3_key_func)(sqlite3*, const void*, int) = null;
325                 void* handle = dlopen(_DATABASE_LIBRARY_PATH, RTLD_LAZY | RTLD_LOCAL);
326                 SysTryReturnResult(NID_IO, handle != null, E_SYSTEM,
327                                 "Failed to dlopen database library file (%s)", dlerror());
328
329                 sqlite3_key_func = reinterpret_cast< int (*)(sqlite3*, const void*, int) >(dlsym(handle, _DATABASE_ENCRYPTION_SYMBOL));
330                 if (sqlite3_key_func == null)
331                 {
332                         SysLog(NID_IO, "This operation is not supported. (%s)", dlerror());
333                         dlclose(handle);
334                         r = E_UNSUPPORTED_OPERATION;
335                         goto CATCH;
336                 }
337
338                 ret = sqlite3_key_func(pDb, pDbKey.get(), MAX_DATABASE_AES_KEY_LENGTH * 2);
339                 dlclose(handle);
340 #endif
341                 if (ret != SQLITE_OK)
342                 {
343                         r = __ConvertNativeSqliteErrorToResult(ret);
344                         SysLog(NID_IO, "[%s] sqlite3_key() failed (%d, %s).", GetErrorMessage(r), ret, sqlite3_errmsg(pDb));
345                         goto CATCH;
346                 }
347         }
348
349         __pDatabase = pDb;
350         __dbName = dbPath;
351
352         return E_SUCCESS;
353
354 CATCH:
355         return r;
356 }
357
358 result
359 _DatabaseImpl::Construct(const String& dbPath, const char* pOpenMode, const ByteBuffer* pSecretKey)
360 {
361         SysAssertf(__pDatabase == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class\n");
362         SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(dbPath, _AppInfo::IsOspCompat()) == true,
363                         E_INVALID_ARG, "The specified dbPath (%ls) is invalid.", dbPath.GetPointer());
364         SysTryReturnResult(NID_IO, !(pSecretKey && pSecretKey->GetRemaining() <= 0), E_INVALID_ARG,
365                         "The specified secretKey is invalid.");
366
367         long legacyMode = 0;
368         bool isValidOpenMode = _DatabaseImpl::VerifyDatabaseOpenMode(pOpenMode, legacyMode);
369         SysTryReturnResult(NID_IO, isValidOpenMode == true, E_INVALID_ARG, "The specified openMode is invalid. (%s)", pOpenMode);
370
371         int ret = 0;
372         int openFlags = 0;
373         sqlite3* pDb = null;
374         bool isFilePathExist = false;
375         bool isParentDirPathExist = false;
376         int lastIndex = -1;
377         String parentDirPath;
378
379         switch (legacyMode)
380         {
381         case DB_OPEN_READ_WRITE:
382                 openFlags = SQLITE_OPEN_READWRITE;
383                 break;
384         case DB_OPEN_READ_ONLY:
385                 openFlags = SQLITE_OPEN_READONLY;
386                 break;
387         case (DB_OPEN_READ_WRITE | DB_OPEN_CREATE):
388                 openFlags = (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
389                 break;
390         default:
391                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
392                 return E_INVALID_ARG;
393         }
394
395         // extract directory path from a given Db file path
396         // Find index of last occurrence  of character '/' in dbPath
397         result r = dbPath.LastIndexOf(L'/', dbPath.GetLength() - 1, lastIndex);
398         SysTryReturnResult(NID_IO, !IsFailed(r), E_INVALID_ARG,
399                         "Missing directory path. SHOULD not happen.");
400
401         // extract directory path from dbPath starting from index 0 to lastIndex.
402         r = dbPath.SubString(0, lastIndex, parentDirPath);
403         SysTryReturnResult(NID_IO, !IsFailed(r), E_INVALID_ARG,
404                         "Missing directory path. SHOULD not happen.");
405
406         // TODO: Test sqlite3_open_v3() without parent directory.
407         //check existence of parent directory
408         isParentDirPathExist = _FileImpl::IsFileExist(String(parentDirPath));
409         SysTryReturnResult(NID_IO, isParentDirPathExist == true, E_INVALID_ARG,
410                            "Parent Directory dose not exist.");
411
412         unique_ptr<char[]> pDbPath(_StringConverter::CopyToCharArrayN(dbPath));
413         SysTryReturn(NID_IO, pDbPath, GetLastResult(), GetLastResult(), "[%s] pDbPath is null.", GetErrorMessage(GetLastResult()));
414
415         //check existence of file
416         isFilePathExist = _FileImpl::IsFileExist(dbPath);
417         if (isFilePathExist == true)
418         {
419                 //check if it is a directory
420                 SysTryReturnResult(NID_IO, !IsDirectory(dbPath), E_INVALID_ARG, "Given path is not a File.");
421
422 #if 0
423                 _DatabaseMode dbMode = DATABASE_MODE_NONE;
424                 dbMode = _SecureIoUtil::GetDatabaseMode(pDbPath.get());
425                 SysTryReturnResult(NID_IO, dbMode != DATABASE_MODE_ERROR, E_INVALID_FORMAT,
426                                 "GetDatabaseMode function failed.");
427
428                 if (pSecretKey && _SecureIoUtil::IsNormalDatabase(dbMode))
429                 {
430                         SysTryReturnResult(NID_IO, false, E_INVALID_ARG,
431                                         "Trying to open a normal database in secure mode.");
432                 }
433                 else if (!pSecretKey && _SecureIoUtil::IsSecureDatabase(dbMode))
434                 {
435                         SysTryReturnResult(NID_IO, false, E_INVALID_ARG,
436                                         "Trying to open a secure database in normal mode.");
437                 }
438                 else
439                 {
440                         //Do Nothing
441                 }
442 #endif
443         }
444         else
445         {
446                 if (legacyMode == DB_OPEN_READ_WRITE || legacyMode == DB_OPEN_READ_ONLY)
447                 {
448                         SysLog(NID_IO, "[E_FILE_NOT_FOUND] File not found.");
449                         r = E_FILE_NOT_FOUND;
450                         goto CATCH;
451                 }
452         }
453
454         // open/create the database
455         ret = sqlite3_open_v2(pDbPath.get(), &pDb, openFlags, null);
456         if (ret != SQLITE_OK)
457         {
458                 if (!_AppInfo::IsOspCompat())
459                 {
460                         r = __ConvertNativeSqliteErrorToDetailResult(ret);
461                         switch (r)
462                         {
463                         case E_INVALID_ARG:
464                         case E_OBJECT_LOCKED:
465                         case E_INVALID_OPERATION:
466                         case E_UNKNOWN:
467                                 r = E_SYSTEM;
468                                 break;
469                         }
470                 }
471                 else
472                 {
473                         r = __ConvertNativeSqliteErrorToResult(ret);
474                 }
475
476                 SysLog(NID_IO, "[%s] Failed to open database file (%s). (%d, %s).", GetErrorMessage(r), pDbPath.get(),
477                                 ret, sqlite3_errmsg(static_cast< sqlite3* >(pDb)));
478                 goto CATCH;
479         }
480
481         if (pSecretKey)
482         {
483                 unique_ptr<byte[]> pDbKey(_SecureIoUtil::GenerateDatabaseKeyN(pSecretKey));
484                 SysTryReturnResult(NID_IO, pDbKey != null, E_IO, "GenerateDatabaseKeyN returned null.");
485
486 #if 0
487                 bool secure = false;
488                 r = SystemInfo::GetValue(L"http://tizen.org/feature/database.encryption", secure);
489                 SysTryReturnResult(NID_IO, !IsFailed(r), E_SYSTEM, "The method cannot proceed due to a severe system error.");
490                 SysTryReturnResult(NID_IO, secure == true, E_UNSUPPORTED_OPERATION, "This operation is not supported.");
491
492                 ret = sqlite3_key(pDb, pDbKey.get(), MAX_DATABASE_AES_KEY_LENGTH * 2);
493 #else
494                 int (* sqlite3_key_func)(sqlite3*, const void*, int) = null;
495                 void* handle = dlopen(_DATABASE_LIBRARY_PATH, RTLD_LAZY | RTLD_LOCAL);
496                 SysTryReturnResult(NID_IO, handle != null, E_SYSTEM,
497                                 "Failed to dlopen database library file (%s)", dlerror());
498
499                 sqlite3_key_func = reinterpret_cast< int (*)(sqlite3*, const void*, int) >(dlsym(handle, _DATABASE_ENCRYPTION_SYMBOL));
500                 if (sqlite3_key_func == null)
501                 {
502                         SysLog(NID_IO, "This operation is not supported. (%s)", dlerror());
503                         dlclose(handle);
504                         r = E_UNSUPPORTED_OPERATION;
505                         goto CATCH;
506                 }
507
508                 ret = sqlite3_key_func(pDb, pDbKey.get(), MAX_DATABASE_AES_KEY_LENGTH * 2);
509                 dlclose(handle);
510 #endif
511                 if (ret != SQLITE_OK)
512                 {
513                         if (!_AppInfo::IsOspCompat())
514                         {
515                                 r = E_INVALID_ARG;
516                         }
517                         else
518                         {
519                                 r = E_DATABASE;
520                         }
521
522                         SysLog(NID_IO, "[%s] Failed to create secret key (%d, %s).", GetErrorMessage(r), ret,
523                                         sqlite3_errmsg(static_cast< sqlite3* >(pDb)));
524                         goto CATCH;
525                 }
526         }
527
528         __pDatabase = pDb;
529         __dbName = dbPath;
530
531         return E_SUCCESS;
532
533 CATCH:
534         return r;
535 }
536
537 DbStatement*
538 _DatabaseImpl::CreateStatementN(const String& statement)
539 {
540         SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
541
542         int ret = 0;
543         char* pStrStmt = null;
544         sqlite3_stmt* pSqlStmt = null;
545         result r = E_SUCCESS;
546
547         unique_ptr<DbStatement> pDbStatement(_DbStatementImpl::CreateDbStatementInstanceN());
548
549         SysTryReturn(NID_IO, pDbStatement != null, null, E_OUT_OF_MEMORY,
550                            "[E_OUT_OF_MEMORY] The memory is insufficient.");
551
552         unique_ptr<char[]> pUnTrimStatement(_StringConverter::CopyToCharArrayN(statement));
553         if (pUnTrimStatement == null)
554         {
555                 r = GetLastResult();
556                 goto CATCH;
557         }
558
559         // trim leading spaces
560         pStrStmt = pUnTrimStatement.get();
561         while ((*pStrStmt == ' ') || (*pStrStmt == '\t'))
562         {
563                 pStrStmt++;
564         }
565
566         // prepare the sql statement
567         ret = sqlite3_prepare_v2((sqlite3*) __pDatabase, pStrStmt, strlen(pStrStmt), &pSqlStmt, null);
568         if (ret != SQLITE_OK)
569         {
570                 if (!_AppInfo::IsOspCompat())
571                 {
572                         r = __ConvertNativeSqliteErrorToDetailResult(ret);
573                         switch (ret)
574                         {
575                         case E_ILLEGAL_ACCESS:
576                         case E_IO:
577                         case E_INVALID_FORMAT:
578                         case E_STORAGE_FULL:
579                         case E_INVALID_OPERATION:
580                         case E_UNKNOWN:
581                                 r = E_SYSTEM;
582                                 break;
583                         }
584                 }
585                 else
586                 {
587                         r = __ConvertNativeSqliteErrorToResult(ret);
588                 }
589
590                 SysLog(NID_IO, "[%s] Failed to prepare SQL statement (%s). (%d, %s).", GetErrorMessage(r), pStrStmt,
591                                 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
592                 goto CATCH;
593         }
594
595         // register the sql stmt in DbStatement
596         // accessing private variable of DbStatement.
597         _DbStatementImpl::GetInstance(*pDbStatement)->__pStmt = pSqlStmt;
598         _DbStatementImpl::GetInstance(*pDbStatement)->__pDatabase = __pDatabase;
599
600         if (strncasecmp(pStrStmt, "select", 6) == 0)
601         {
602                 _DbStatementImpl::GetInstance(*pDbStatement)->__stmtType = DB_STATEMENT_TYPE_SELECT;
603         }
604         else
605         {
606                 _DbStatementImpl::GetInstance(*pDbStatement)->__stmtType = DB_STATEMENT_TYPE_OTHER;
607         }
608
609         ClearLastResult();
610         return pDbStatement.release();
611
612 CATCH:
613         SetLastResult(r);
614         return null;
615 }
616
617 DbEnumerator*
618 _DatabaseImpl::ExecuteStatementN(const DbStatement& statement)
619 {
620         SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
621         SysTryReturn(NID_IO, _DbStatementImpl::GetInstance(statement)->__pStmt != null, null, E_INVALID_ARG,
622                            "[E_INVALID_ARG] Invalid DbStatement was passed.(null handle was assigned)");
623
624         int ret = 0;
625         DbEnumerator* pDbEnum = null;
626         result r = E_SUCCESS;
627
628         ret = sqlite3_reset((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
629         if (ret != SQLITE_OK)
630         {
631                 if (!_AppInfo::IsOspCompat())
632                 {
633                         r = __ConvertNativeSqliteErrorToDetailResult(ret);
634                         switch (ret)
635                         {
636                                 case E_INVALID_ARG:
637                                 case E_ILLEGAL_ACCESS:
638                                 case E_IO:
639                                 case E_INVALID_FORMAT:
640                                 case E_STORAGE_FULL:
641                                 case E_INVALID_OPERATION:
642                                 case E_UNKNOWN:
643                                         r = E_SYSTEM;
644                                         break;
645                         }
646                 }
647                 else
648                 {
649                         r = __ConvertNativeSqliteErrorToResult(ret);
650                 }
651
652                 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
653                                 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
654                 goto CATCH;
655         }
656
657 REDO_SQLITE_STEP:
658         ret = sqlite3_step((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
659         switch (ret)
660         {
661         case SQLITE_OK:
662         case SQLITE_DONE:
663                 ret = sqlite3_reset((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
664                 if (ret != SQLITE_OK)
665                 {
666                         if (!_AppInfo::IsOspCompat())
667                         {
668                                 r = __ConvertNativeSqliteErrorToDetailResult(ret);
669                                 switch (ret)
670                                 {
671                                 case E_INVALID_ARG:
672                                 case E_ILLEGAL_ACCESS:
673                                 case E_IO:
674                                 case E_INVALID_FORMAT:
675                                 case E_STORAGE_FULL:
676                                 case E_INVALID_OPERATION:
677                                 case E_UNKNOWN:
678                                         r = E_SYSTEM;
679                                         break;
680                                 }
681                         }
682                         else
683                         {
684                                 r = __ConvertNativeSqliteErrorToResult(ret);
685                         }
686
687                         SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
688                                         ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
689                         goto CATCH;
690                 }
691                 break;
692
693         case SQLITE_ROW:
694                 if (_DbStatementImpl::GetInstance(statement)->__stmtType == DB_STATEMENT_TYPE_SELECT)
695                 {
696                         unique_ptr<DbEnumerator> pTempDbEnum(_DbEnumeratorImpl::CreateDbEnumeratorInstanceN());
697
698                         SysTryReturn(NID_IO, pTempDbEnum != null, null, E_OUT_OF_MEMORY,
699                                         "[E_OUT_OF_MEMORY] The memory is insufficient.");
700
701                         _DbEnumeratorImpl::GetInstance(*pTempDbEnum)->__pEnum = _DbStatementImpl::GetInstance(statement)->__pStmt;
702                         _DbEnumeratorImpl::GetInstance(*pTempDbEnum)->__pDatabase = _DbStatementImpl::GetInstance(statement)->__pDatabase;
703
704 #if 1
705                         ret = sqlite3_reset((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
706                         if (ret != SQLITE_OK)
707                         {
708                                 if (!_AppInfo::IsOspCompat())
709                                 {
710                                         r = __ConvertNativeSqliteErrorToDetailResult(ret);
711                                         switch (ret)
712                                         {
713                                         case E_INVALID_ARG:
714                                         case E_ILLEGAL_ACCESS:
715                                         case E_IO:
716                                         case E_INVALID_FORMAT:
717                                         case E_STORAGE_FULL:
718                                         case E_INVALID_OPERATION:
719                                         case E_UNKNOWN:
720                                                 r = E_SYSTEM;
721                                                 break;
722                                         }
723                                 }
724                                 else
725                                 {
726                                         r = __ConvertNativeSqliteErrorToResult(ret);
727                                 }
728
729                                 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
730                                                 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
731                                 goto CATCH;
732                         }
733 #endif
734
735                         pDbEnum = pTempDbEnum.release();
736
737                 }
738                 else
739                 {
740                         goto REDO_SQLITE_STEP;
741                 }
742                 break;
743
744         default:
745                 if (!_AppInfo::IsOspCompat())
746                 {
747                         r = __ConvertNativeSqliteErrorToDetailResult(ret);
748                         switch (r)
749                         {
750                         case E_ILLEGAL_ACCESS:
751                         case E_INVALID_OPERATION:
752                         case E_UNKNOWN:
753                                 r = E_SYSTEM;
754                                 break;
755                         }
756                 }
757                 else
758                 {
759                         r = __ConvertNativeSqliteErrorToResult(ret);
760                 }
761
762                 SysLog(NID_IO, "[%s] Failed to execute SQL statement. (%d, %s).", GetErrorMessage(r), ret,
763                                 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
764                 goto CATCH;
765         }
766
767         SetLastResult(E_SUCCESS);
768         return pDbEnum;
769
770 CATCH:
771         SetLastResult(r);
772         return null;
773 }
774
775 result
776 _DatabaseImpl::ExecuteSql(const String& sql, bool autoCommit)
777 {
778         SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
779
780         int ret = 0;
781         char* pSqlStr = null;
782         result r = E_SUCCESS;
783
784         unique_ptr<char[]> pUnTrimStatement(_StringConverter::CopyToCharArrayN(sql));
785         if (pUnTrimStatement == null)
786         {
787                 r = GetLastResult();
788                 goto CATCH;
789         }
790
791         // trim leading spaces
792         pSqlStr = pUnTrimStatement.get();
793         while ((*pSqlStr == ' ') || (*pSqlStr == '\t'))
794         {
795                 pSqlStr++;
796         }
797
798         if (strncasecmp(pSqlStr, "select", 6) == 0)
799         {
800                 r = E_INVALID_OPERATION;
801                 goto CATCH;
802         }
803
804         ret = sqlite3_exec((sqlite3*) __pDatabase, pSqlStr, null, null, null);
805         if (ret != SQLITE_OK)
806         {
807                 if (!_AppInfo::IsOspCompat())
808                 {
809                         r = __ConvertNativeSqliteErrorToDetailResult(ret);
810                         switch (r)
811                         {
812                         case E_ILLEGAL_ACCESS:
813                         case E_INVALID_OPERATION:
814                         case E_UNKNOWN:
815                                 r = E_SYSTEM;
816                                 break;
817                         }
818                 }
819                 else
820                 {
821                         r = __ConvertNativeSqliteErrorToResult(ret);
822                 }
823
824                 SysLog(NID_IO, "[%s] Failed to execute SQL statement. (%d, %s).", GetErrorMessage(r), ret,
825                                 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
826                 goto CATCH;
827         }
828
829         return E_SUCCESS;
830
831 CATCH:
832         return r;
833 }
834
835 DbEnumerator*
836 _DatabaseImpl::QueryN(const String& query)
837 {
838         SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
839
840         int ret = 0;
841         char* pQuery = null;
842         sqlite3_stmt* pSqlStmt = null;
843         unique_ptr<DbEnumerator> pDbEnum(null);
844         result r = E_SUCCESS;
845
846         unique_ptr<char[]> pUnTrimStatement(_StringConverter::CopyToCharArrayN(query));
847         if (pUnTrimStatement == null)
848         {
849                 r = GetLastResult();
850                 goto CATCH;
851         }
852
853         // trim leading spaces
854         pQuery = pUnTrimStatement.get();
855         while ((*pQuery == ' ') || (*pQuery == '\t'))
856         {
857                 pQuery++;
858         }
859
860         if (strncasecmp(pQuery, "select", 6) != 0)
861         {
862                 r = E_INVALID_OPERATION;
863                 goto CATCH;
864         }
865
866         // prepare the sql statement
867         ret = sqlite3_prepare_v2((sqlite3*) __pDatabase, pQuery, strlen(pQuery), &pSqlStmt, null);
868         if (ret != SQLITE_OK)
869         {
870                 if (!_AppInfo::IsOspCompat())
871                 {
872                         r = __ConvertNativeSqliteErrorToDetailResult(ret);
873                         switch (ret)
874                         {
875                         case E_ILLEGAL_ACCESS:
876                         case E_IO:
877                         case E_INVALID_FORMAT:
878                         case E_STORAGE_FULL:
879                         case E_INVALID_OPERATION:
880                         case E_UNKNOWN:
881                                 r = E_SYSTEM;
882                                 break;
883                         }
884                 }
885                 else
886                 {
887                         r = __ConvertNativeSqliteErrorToResult(ret);
888                 }
889
890                 SysLog(NID_IO, "[%s] Failed to prepare SQL statement (%s). (%d, %s).", GetErrorMessage(r), pQuery,
891                                 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
892                 goto CATCH;
893         }
894
895 //    ret = sqlite3_reset((sqlite3_stmt *) pSqlStmt);
896 //      if (ret != SQLITE_OK)
897 //      {
898 //              r = __ConvertNativeSqliteErrorToResult(ret);
899 //              SysLog(NID_IO, "[_DatabaseImpl] ERROR: [%s] Failed to reset SQL statement.", GetErrorMessage(r));
900 //              goto CATCH;
901 //      }
902
903         ret = sqlite3_step(pSqlStmt);
904         switch (ret)
905         {
906         case SQLITE_OK:
907         case SQLITE_DONE:
908                 break;
909
910         case SQLITE_ROW:
911                 pDbEnum.reset(_DbEnumeratorImpl::CreateDbEnumeratorInstanceN());
912
913                 SysTryCatch(NID_IO, pDbEnum != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
914                                 "[E_OUT_OF_MEMORY] The memory is insufficient.");
915
916                 _DbEnumeratorImpl::GetInstance(*pDbEnum)->__pEnum = pSqlStmt;
917                 _DbEnumeratorImpl::GetInstance(*pDbEnum)->__pDatabase = __pDatabase;
918                 _DbEnumeratorImpl::GetInstance(*pDbEnum)->__shouldReleaseResource = true;
919
920                 // doing a reset again, so that enumerator first MoveNext() give the first row.
921                 ret = sqlite3_reset((sqlite3_stmt*) pSqlStmt);
922                 if (ret != SQLITE_OK)
923                 {
924                         if (!_AppInfo::IsOspCompat())
925                         {
926                                 r = __ConvertNativeSqliteErrorToDetailResult(ret);
927                                 switch (ret)
928                                 {
929                                         case E_INVALID_ARG:
930                                         case E_ILLEGAL_ACCESS:
931                                         case E_IO:
932                                         case E_INVALID_FORMAT:
933                                         case E_STORAGE_FULL:
934                                         case E_INVALID_OPERATION:
935                                         case E_UNKNOWN:
936                                                 r = E_SYSTEM;
937                                                 break;
938                                 }
939                         }
940                         else
941                         {
942                                 r = __ConvertNativeSqliteErrorToResult(ret);
943                         }
944
945                         SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
946                                 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
947                         goto CATCH;
948                 }
949                 break;
950
951         default:
952                 if (!_AppInfo::IsOspCompat())
953                 {
954                         r = __ConvertNativeSqliteErrorToDetailResult(ret);
955                         switch (r)
956                         {
957                         case E_ILLEGAL_ACCESS:
958                         case E_STORAGE_FULL:
959                         case E_INVALID_OPERATION:
960                         case E_UNKNOWN:
961                                 r = E_SYSTEM;
962                                 break;
963                         }
964                 }
965                 else
966                 {
967                         r = __ConvertNativeSqliteErrorToResult(ret);
968                 }
969
970                 SysLog(NID_IO, "[%s] Failed to exectue SQL statement (%s). (%d, %s).", GetErrorMessage(r), pQuery,
971                                 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
972                 goto CATCH;
973         }
974
975         ClearLastResult();
976         return pDbEnum.release();
977
978 CATCH:
979         sqlite3_finalize(pSqlStmt);
980         SetLastResult(r);
981         return null;
982 }
983
984 result
985 _DatabaseImpl::BeginTransaction(void)
986 {
987         SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
988         SysTryReturnResult(NID_IO, __transactionGoingOn == false, E_INVALID_STATE,
989                                 "A transaction is already in progress.");
990
991         result r = E_SUCCESS;
992
993         if (sqlite3_get_autocommit((sqlite3*) __pDatabase) == 0)
994         {
995                 SysLog(NID_IO, "[E_INVALID_STATE] Already in transaction mode.");
996                 return E_INVALID_STATE;
997         }
998
999         int ret = sqlite3_exec((sqlite3*) __pDatabase, "BEGIN", null, null, null);
1000         if (ret != SQLITE_OK)
1001         {
1002                 if (!_AppInfo::IsOspCompat())
1003                 {
1004                         r = __ConvertNativeSqliteErrorToDetailResult(ret);
1005                         switch (r)
1006                         {
1007                         case E_INVALID_ARG:
1008                         case E_ILLEGAL_ACCESS:
1009                         case E_OBJECT_LOCKED:
1010                         case E_IO:
1011                         case E_INVALID_FORMAT:
1012                         case E_STORAGE_FULL:
1013                         case E_INVALID_OPERATION:
1014                                 r = E_SYSTEM;
1015                                 break;
1016                         }
1017                 }
1018                 else
1019                 {
1020                         r = __ConvertNativeSqliteErrorToResult(ret);
1021                 }
1022
1023                 SysLog(NID_IO, "[%s] Failed to begin transaction. (%d, %s)", GetErrorMessage(r), ret,
1024                                 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
1025         }
1026         else
1027         {
1028                 __transactionGoingOn = true;
1029         }
1030
1031         return r;
1032 }
1033
1034 result
1035 _DatabaseImpl::CommitTransaction(void)
1036 {
1037         SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1038         SysTryReturnResult(NID_IO, __transactionGoingOn == true, E_INVALID_STATE,
1039                                 "A transaction is already in progress.");
1040
1041         int ret = 0;
1042         result r = E_SUCCESS;
1043
1044         if (sqlite3_get_autocommit((sqlite3*) __pDatabase) != 0)
1045         {
1046                 SysLog(NID_IO, "[E_INVALID_STATE] ERROR Message: Not in transaction mode.");
1047                 return E_INVALID_STATE;
1048         }
1049
1050         ret = sqlite3_exec((sqlite3*) __pDatabase, "COMMIT", null, null, null);
1051         if (ret != SQLITE_OK)
1052         {
1053                 if (!_AppInfo::IsOspCompat())
1054                 {
1055                         r = __ConvertNativeSqliteErrorToDetailResult(ret);
1056                         switch (r)
1057                         {
1058                         case E_INVALID_ARG:
1059                         case E_ILLEGAL_ACCESS:
1060                         case E_INVALID_OPERATION:
1061                                 r = E_SYSTEM;
1062                                 break;
1063                         }
1064                 }
1065                 else
1066                 {
1067                         r = __ConvertNativeSqliteErrorToResult(ret);
1068                 }
1069
1070                 SysLog(NID_IO, "[%s] Failed to commit transaction. (%d, %s)", GetErrorMessage(r), ret,
1071                                 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
1072         }
1073         else
1074         {
1075                 __transactionGoingOn = false;
1076         }
1077
1078         return r;
1079 }
1080
1081 result
1082 _DatabaseImpl::RollbackTransaction(void)
1083 {
1084         SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1085         SysTryReturnResult(NID_IO, __transactionGoingOn == true, E_INVALID_STATE,
1086                                 "No transaction in progress.");
1087
1088         int ret = 0;
1089         result r = E_SUCCESS;
1090
1091         if (sqlite3_get_autocommit((sqlite3*) __pDatabase) != 0)
1092         {
1093                 SysLog(NID_IO, "[E_SUCCESS] No transaction in progress.");
1094                 //return E_INVALID_STATE;
1095                 return E_SUCCESS;
1096         }
1097
1098         ret = sqlite3_exec((sqlite3*) __pDatabase, "ROLLBACK", null, null, null);
1099         if (ret != SQLITE_OK)
1100         {
1101                 if (!_AppInfo::IsOspCompat())
1102                 {
1103                         r = __ConvertNativeSqliteErrorToDetailResult(ret);
1104                         switch (r)
1105                         {
1106                         case E_INVALID_ARG:
1107                         case E_ILLEGAL_ACCESS:
1108                         case E_INVALID_OPERATION:
1109                                 r = E_SYSTEM;
1110                                 break;
1111                         }
1112                 }
1113                 else
1114                 {
1115                         r = __ConvertNativeSqliteErrorToResult(ret);
1116                 }
1117
1118                 SysLog(NID_IO, "[%s] Failed to rollback the transaction. (%d, %s)", GetErrorMessage(r), ret,
1119                                 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
1120         }
1121         else
1122         {
1123                 __transactionGoingOn = false;
1124         }
1125
1126         return r;
1127 }
1128
1129 String
1130 _DatabaseImpl::GetName(void) const
1131 {
1132         SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1133
1134         SetLastResult(E_SUCCESS);
1135         return __dbName;
1136 }
1137
1138 result
1139 _DatabaseImpl::RegisterUserFunction(const String& functionName, const int argumentCount, void* pUserData,
1140                                                                         _IDbUserFunctionListener* pUserFunctionListener,
1141                                                                         _IDbUserAggregateListener* pUserAggregateListener)
1142 {
1143         result r = E_SUCCESS;
1144         int sqliteEncoding = 0;
1145         int ret = 0;
1146         int utf8len = 0;
1147         unique_ptr<_DbContextImpl> pDbContext(null);
1148         _DbContextImpl* pTempDbContext = null;
1149         bool entryFound = false;
1150         int i = 0;
1151
1152         // Validate input parameters
1153         SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1154         SysTryReturnResult(NID_IO, functionName.GetLength() > 0, E_INVALID_ARG,
1155                         "Invalid funcName length.");
1156         SysTryReturnResult(NID_IO, argumentCount >= 0 && argumentCount <= MAX_FUNCTION_ARGUMENT_COUNT, E_INVALID_ARG,
1157                                 "argumentCount < 0 or > 127.");
1158
1159         if (pUserFunctionListener != null && pUserAggregateListener != null)
1160         {
1161                 SysTryReturnResult(NID_IO, 0, E_INVALID_ARG,
1162                                         "FunctionListener and AggregateListener cannot be registered together");
1163         }
1164
1165         //select the equivalent sqlite encoding.
1166
1167         unique_ptr<ByteBuffer> pFuncNameBuf(StringUtil::StringToUtf8N(functionName));
1168         SysTryReturn(NID_IO, pFuncNameBuf != null, GetLastResult(),
1169                                 GetLastResult(), "[%s] Invalid Function name.", GetErrorMessage(GetLastResult()));
1170
1171         utf8len = pFuncNameBuf->GetLimit();
1172         SysTryReturnResult(NID_IO, utf8len > 0 && utf8len <= MAX_UTF8_BYTES, E_INVALID_ARG,
1173                            "functionName length in utf8 bytes should be >0 && <=255.");
1174
1175         sqliteEncoding = SQLITE_UTF8; // support only UTF8
1176
1177         //check if the (FunctionName, argumentCount) already exist in the list
1178         for (i = 0; i < __userFunctionContextList.GetCount(); i++)
1179         {
1180                 pTempDbContext = dynamic_cast<_DbContextImpl*> (__userFunctionContextList.GetAt(i));
1181                 SysTryReturnResult(NID_IO, pTempDbContext, E_IO, "The __userFunctionContextList has an invalid element.");
1182                 if ((pTempDbContext->__argumentCount == argumentCount) &&
1183                         (pTempDbContext->__functionName == functionName))
1184                 {
1185                         entryFound = true;
1186                         break;
1187                 }
1188         }
1189
1190         if (entryFound && (null != pUserFunctionListener || null != pUserAggregateListener))
1191         {
1192                 SysTryReturnResult(NID_IO, 0, E_INVALID_ARG,
1193                                    "(functionName, argumentCount) already registered");
1194         }
1195
1196         if (pUserFunctionListener != null) // register FunctionListener
1197         {
1198                 pDbContext.reset(new (std::nothrow) _DbContextImpl());
1199                 SysTryReturnResult(NID_IO, pDbContext != null, E_OUT_OF_MEMORY,
1200                                 "The memory is insufficient.");
1201
1202                 ret = sqlite3_create_function((sqlite3*) __pDatabase,
1203                         (const char*) pFuncNameBuf->GetPointer(), argumentCount, sqliteEncoding, pDbContext.get(),
1204                         _DatabaseImpl::UserFunctionListener, null, null);
1205         }
1206         else if (pUserAggregateListener != null) // register both FunctionStepListener and FunctionFinalListener
1207         {
1208                 pDbContext.reset(new (std::nothrow) _DbContextImpl());
1209
1210                 SysTryReturnResult(NID_IO, pDbContext != null, E_OUT_OF_MEMORY,
1211                                 "The memory is insufficient.");
1212
1213                 ret = sqlite3_create_function((sqlite3*) __pDatabase,
1214                         (const char*) pFuncNameBuf->GetPointer(), argumentCount, sqliteEncoding, pDbContext.get(),
1215                          null, _DatabaseImpl::UserFunctionStepListener, _DatabaseImpl::UserFunctionFinalListener);
1216         }
1217         else // Delete registered user function/Aggregate
1218         {
1219                 ret = sqlite3_create_function((sqlite3*) __pDatabase,
1220                          (const char*) pFuncNameBuf->GetPointer(), argumentCount, sqliteEncoding, null, null, null, null);
1221         }
1222
1223         if (ret != SQLITE_OK) //error
1224         {
1225                 r = __ConvertNativeSqliteErrorToResult(ret);
1226                 SysLog(NID_IO, "[%s] ERROR Message: [%s], Failed to create/delete user defined SQL function.", GetErrorMessage(r),
1227                                         sqlite3_errmsg((sqlite3*)__pDatabase));
1228                 return r;
1229         }
1230
1231         if (entryFound && (!pUserFunctionListener && !pUserAggregateListener)) // delete the user function entry from list
1232         {
1233                 r = __userFunctionContextList.Remove(*pTempDbContext, true);
1234                 SysTryReturn(NID_IO, !IsFailed(r), GetLastResult(),
1235                                         GetLastResult(), "[%s] Failed to remove user function context to the list.", GetErrorMessage(GetLastResult()));
1236         }
1237
1238         if (pDbContext != null)
1239         {
1240                 //store listener and user data
1241                 pDbContext->__pUserData = pUserData;
1242                 pDbContext->__argumentCount = argumentCount;
1243                 pDbContext->__functionName = functionName;
1244                 if (pUserFunctionListener != null)
1245                 {
1246                         pDbContext->__pUserFunctionListener = pUserFunctionListener;
1247                 }
1248                 if (pUserAggregateListener != null)
1249                 {
1250                         pDbContext->__pUserAggregateListener = pUserAggregateListener;
1251                 }
1252
1253                 // add entry to the list
1254                 r = __userFunctionContextList.Add(*(pDbContext.release()));
1255                 SysTryReturn(NID_IO, !IsFailed(r), GetLastResult(),
1256                                         GetLastResult(), "[%s] Failed to add user function context to the list.", GetErrorMessage(GetLastResult()));
1257         }
1258
1259         return E_SUCCESS;
1260 }
1261
1262 result
1263 _DatabaseImpl::RegisterUserCollation(const String& collationName, void* pUserData,
1264                                                                          _IDbUserCollationListener* pUserCollationListener)
1265 {
1266         result r = E_SUCCESS;
1267         int sqliteEncoding = 0;
1268         int ret = 0;
1269         int utf8len = 0;
1270         unique_ptr<_DbContextImpl> pDbContext(null);
1271         _DbContextImpl* pTempDbContext = null;
1272         bool entryFound = false;
1273         int i = 0;
1274
1275         SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1276         SysTryReturnResult(NID_IO, collationName.GetLength() > 0, E_INVALID_ARG,
1277                         "Invalid collationName length.");
1278
1279         sqliteEncoding = SQLITE_UTF8; // support only UTF8
1280
1281         unique_ptr<ByteBuffer> pColNameBuf(StringUtil::StringToUtf8N(collationName));
1282         SysTryReturn(NID_IO, pColNameBuf != null, GetLastResult(), GetLastResult(), "[%s] Invalid Function name.",
1283                                 GetErrorMessage(GetLastResult()));
1284
1285         utf8len = pColNameBuf->GetLimit(); // get UTF_8 bytes length
1286         SysTryReturnResult(NID_IO, utf8len > 0 && utf8len <= MAX_UTF8_BYTES, E_INVALID_ARG,
1287                         "functionName length in utf8 bytes should be >0 && <=255.");
1288
1289         //check if the (FunctionName) already registered
1290         for (i = 0; i < __userCollationContextList.GetCount(); i++)
1291         {
1292                 pTempDbContext = dynamic_cast< _DbContextImpl* >(__userCollationContextList.GetAt(i));
1293                 SysTryReturnResult(NID_IO, pTempDbContext, E_IO, "The __userCollationContextList has an invalid element.");
1294                 if (pTempDbContext->__collationName == collationName)
1295                 {
1296                         entryFound = true;
1297                         break;
1298                 }
1299         }
1300
1301         if (entryFound && (pUserCollationListener != null)) // check if the operation is to delete the user function
1302         {
1303                 SysTryReturnResult(NID_IO, 0, E_INVALID_ARG, "(collationName) already registered");
1304         }
1305
1306         if (pUserCollationListener != null)
1307         {
1308                 pDbContext.reset(new (std::nothrow) _DbContextImpl());
1309                 SysTryReturnResult(NID_IO, pDbContext != null, E_OUT_OF_MEMORY,
1310                                 "The memory is insufficient.");
1311
1312                 // register CollationListener()
1313                 ret = sqlite3_create_collation((sqlite3*) __pDatabase, (const char*) pColNameBuf->GetPointer(), sqliteEncoding, pDbContext.get(),
1314                                 _DatabaseImpl::UserCollationListener);
1315         }
1316         else // delete Collating function
1317         {
1318                 ret = sqlite3_create_collation((sqlite3*) __pDatabase, (const char*) pColNameBuf->GetPointer(), sqliteEncoding, null, null);
1319         }
1320
1321         if (ret != SQLITE_OK)
1322         {
1323                 r = __ConvertNativeSqliteErrorToResult(ret);
1324                 SysLog(NID_IO, "[%s] ERROR Message: [%s], Failed to create/delete user defined SQL Collation.", GetErrorMessage(r),
1325                                 sqlite3_errmsg((sqlite3*)__pDatabase));
1326                 return r;
1327         }
1328
1329         if (entryFound && !pUserCollationListener) // delete the user collation entry from list
1330         {
1331                 r = __userCollationContextList.Remove(*pTempDbContext, true);
1332                 SysTryReturn(NID_IO, !IsFailed(r), GetLastResult(),
1333                                         GetLastResult(), "[%s] Failed to remove user collation context from the list.", GetErrorMessage(GetLastResult()));
1334         }
1335
1336         if (pDbContext != null)
1337         {
1338                 //store listener and user data
1339                 pDbContext->__pUserData = pUserData;
1340                 pDbContext->__collationName = collationName;
1341                 pDbContext->__pUserCollationListener = pUserCollationListener;
1342                 // add entry to the list
1343                 r = __userCollationContextList.Add((*(pDbContext.release())));
1344                 SysTryReturn(NID_IO, !IsFailed(r), GetLastResult(),
1345                                         GetLastResult(), "[%s] Failed to add user collation context to the list.", GetErrorMessage(GetLastResult()));
1346
1347         }
1348
1349         return E_SUCCESS;
1350 }
1351
1352 long long 
1353 _DatabaseImpl::GetLastInsertRowId(void) const
1354 {
1355         SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1356
1357         // Retrieve last inserted row Id of the specified Db connection.
1358         // sqlite rowIds starts from 1 to max. 0 means no rows available in the database.
1359         // even if we delete the last inserted row, it still returns the rowid of last insert.
1360         // and does not care about any deletions happened.
1361         long long insertRowId = sqlite3_last_insert_rowid(static_cast< sqlite3* >(__pDatabase));
1362         if (insertRowId == 0)
1363         {
1364                 return -1;
1365         }
1366         else
1367         {
1368                 return insertRowId;
1369         }
1370 }
1371
1372 result
1373 _DatabaseImpl::Delete(const String& databasePath)
1374 {
1375         result r = E_SUCCESS;
1376         int ret = 0;
1377
1378         SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(databasePath, _AppInfo::IsOspCompat()) == true,
1379                         E_INVALID_ARG, " [%ls] is not compatible.", databasePath.GetPointer());
1380
1381         unique_ptr<char[]> pDbPath(_StringConverter::CopyToCharArrayN(databasePath));
1382         if (pDbPath == null)
1383         {
1384                 return GetLastResult();
1385         }
1386
1387         // remove the file
1388         ret = unlink(pDbPath.get());
1389         if (ret != 0)
1390         {
1391                 r = __ConvertNativeErrorToResult(errno);
1392         }
1393
1394         return r;
1395 }
1396
1397 bool
1398 _DatabaseImpl::Exists(const String& databasePath)
1399 {
1400         return _FileImpl::IsFileExist(databasePath);
1401 }
1402
1403 void
1404 _DatabaseImpl::UserFunctionListener(sqlite3_context* pContext, int argumentCount, sqlite3_value** pArgList)
1405 {
1406         _DbContextImpl* pDbContext = null;
1407
1408         pDbContext = static_cast< _DbContextImpl* >(sqlite3_user_data(pContext));
1409
1410         SysTryReturnVoidResult(NID_IO, pDbContext, E_INVALID_STATE, "[E_INVALID_STATE] pDbContext is null.");
1411         SysTryReturnVoidResult(NID_IO, pDbContext->__pUserFunctionListener, E_INVALID_STATE,
1412                                         "[E_INVALID_STATE] UserAggregateListener is null.");
1413
1414         //Set DbContext data
1415         if (pDbContext->__pContext != (void*) pContext)
1416         {
1417                 pDbContext->__pContext = (void*) pContext;
1418         }
1419
1420         if (pDbContext->__argumentCount != argumentCount)
1421         {
1422                 SysLog(NID_IO, "Message: __argumentCount mismatch.");
1423                 pDbContext->__argumentCount = argumentCount;
1424         }
1425
1426         if (pDbContext->__pArgList != (void**) pArgList)
1427         {
1428                 pDbContext->__pArgList = (void**) pArgList;
1429         }
1430         // Invoke the user listener method
1431         pDbContext->__pUserFunctionListener->OnDbUserFunction(*pDbContext, argumentCount);
1432
1433         SetLastResult(E_SUCCESS);
1434 }
1435
1436 void
1437 _DatabaseImpl::UserFunctionStepListener(sqlite3_context* pContext, int argumentCount, sqlite3_value** pArgList)
1438 {
1439         _DbContextImpl* pDbContext = null;
1440
1441         pDbContext = static_cast< _DbContextImpl* >(sqlite3_user_data(pContext));
1442
1443         SysTryReturnVoidResult(NID_IO, pDbContext, E_INVALID_STATE, "[E_INVALID_STATE] pDbContext is null.");
1444         SysTryReturnVoidResult(NID_IO, pDbContext->__pUserAggregateListener, E_INVALID_STATE,
1445                                         "[E_INVALID_STATE] __pDbContextImpl->__pUserAggregateListener is null.");
1446
1447         //Set DbContext data
1448         if (pDbContext->__pContext != (void*) pContext)
1449         {
1450                 pDbContext->__pContext = (void*) pContext;
1451         }
1452
1453         if (pDbContext->__argumentCount != argumentCount)
1454         {
1455                 pDbContext->__argumentCount = argumentCount;
1456         }
1457
1458         if (pDbContext->__pArgList != (void**) pArgList)
1459         {
1460                 pDbContext->__pArgList = (void**) pArgList;
1461         }
1462
1463         // invoke the user listener method
1464         pDbContext->__pUserAggregateListener->OnDbUserAggregateStep(*pDbContext, argumentCount);
1465
1466         SetLastResult(E_SUCCESS);
1467 }
1468
1469 void
1470 _DatabaseImpl::UserFunctionFinalListener(sqlite3_context* pContext)
1471 {
1472         _DbContextImpl* pDbContext = null;
1473
1474         pDbContext = static_cast< _DbContextImpl* >(sqlite3_user_data(pContext));
1475
1476         SysTryReturnVoidResult(NID_IO, pDbContext, E_INVALID_STATE, "[E_INVALID_STATE] pDbContext is null.");
1477         SysTryReturnVoidResult(NID_IO, pDbContext->__pUserAggregateListener, E_INVALID_STATE,
1478                                         "[E_INVALID_STATE] UserAggregateListener is null.");
1479
1480         // set context and user data
1481         if (pDbContext->__pContext != (void*) pContext)
1482         {
1483                 pDbContext->__pContext = (void*) pContext;
1484         }
1485
1486         // invoke the user listener method
1487         pDbContext->__pUserAggregateListener->OnDbUserAggregateFinal(*pDbContext);
1488
1489         SetLastResult(E_SUCCESS);
1490 }
1491
1492 int
1493 _DatabaseImpl::UserCollationListener(void* pUserData, int length1, const void* pInput1, int length2, const void* pInput2)
1494 {
1495         _DbContextImpl* pDbContext = null;
1496         char* pDataInput = null;
1497         String string1("");
1498         String string2("");
1499
1500         pDbContext = static_cast< _DbContextImpl* >(pUserData);
1501
1502         SysTryReturn(NID_IO, pDbContext, 0, E_INVALID_STATE, "[E_INVALID_STATE] pDbContext is null.");
1503         SysTryReturn(NID_IO, pDbContext->__pUserCollationListener, 0, E_INVALID_STATE,
1504                                 "[E_INVALID_STATE] UserCollationListener is null.");
1505
1506         if (length1 > 0 && (const char*) pInput1 != null)
1507         {
1508                 pDataInput = (char*) malloc((length1 + 1) * sizeof(char));
1509
1510                 if (pDataInput == null)
1511                 {
1512                         return 0;
1513                 }
1514
1515                 memset(pDataInput, 0, length1 + 1);
1516                 strncpy(pDataInput, (const char*) pInput1, length1);
1517                 string1.Clear();
1518                 string1.Append((const char*) pDataInput);
1519                 free(pDataInput);
1520         }
1521
1522         if (length2 > 0 && (const char*) pInput2 != null)
1523         {
1524                 pDataInput = (char*) malloc((length2 + 1) * sizeof(char));
1525
1526                 if (pDataInput == null)
1527                 {
1528                         return 0;
1529                 }
1530
1531                 memset(pDataInput, 0, length2 + 1);
1532                 strncpy(pDataInput, (const char*) pInput2, length2);
1533                 string2.Clear();
1534                 string2.Append((const char*) pDataInput);
1535                 free(pDataInput);
1536         }
1537
1538         SetLastResult(E_SUCCESS);
1539
1540         return pDbContext->__pUserCollationListener->OnDbUserCollation(string1, string2, pUserData);
1541 }
1542
1543 result
1544 _DatabaseImpl::ConvertToSecureDatabase(const String& plainDbPath, const String& secureDbPath, const ByteBuffer* pKey)
1545 {
1546         result  r = E_SUCCESS;
1547         String  sql;
1548         String  parentDirPath;
1549         FileAttributes  attr;
1550
1551         if (Database::Exists(secureDbPath))
1552         {
1553                 if (GetLastResult() == E_SUCCESS)
1554                 {
1555                         r = File::GetAttributes(secureDbPath, attr);
1556                         if (r == E_SUCCESS)
1557                         {
1558                                 if (attr.IsDirectory())
1559                                 {
1560                                         return E_INVALID_ARG;
1561                                 }
1562                                 else
1563                                 {
1564                                         return E_FILE_ALREADY_EXIST;
1565                                 }
1566                         }
1567                         else
1568                         {
1569                                 return r;
1570                         }
1571                 }
1572                 else
1573                 {
1574                         return E_SYSTEM;
1575                 }
1576         }
1577
1578         unique_ptr<Database>pDatabase(new (std::nothrow) Database());
1579         SysTryReturnResult(NID_IO, pDatabase, E_OUT_OF_MEMORY, "The memory is insufficient.");
1580
1581         r = pDatabase->Construct(secureDbPath, "a+");
1582         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1583
1584         pDatabase.reset(new (std::nothrow) Database());
1585         SysTryReturnResult(NID_IO, pDatabase, E_OUT_OF_MEMORY, "The memory is insufficient.");
1586
1587         r = pDatabase->Construct(plainDbPath, "r+");
1588         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1589
1590         unique_ptr<String> pSqlStr(new (std::nothrow) String(MAX_DATABASE_SQL_LENGTH));
1591         SysTryReturnResult(NID_IO, pSqlStr != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1592
1593         unique_ptr<char[]> pPhysicalDbPath(_StringConverter::CopyToCharArrayN(secureDbPath));
1594         SysTryReturn(NID_IO, pPhysicalDbPath != null, GetLastResult(), GetLastResult(), "[%s] Invalid file path.", GetErrorMessage(GetLastResult()));
1595
1596         unique_ptr<byte[]> pDbKey(_SecureIoUtil::GenerateDatabaseKeyN(pKey));
1597         SysTryReturnResult(NID_IO, pDbKey != null, E_INVALID_ARG, "GenerateDatabaseKeyN returned null.");
1598
1599         pSqlStr->Format(MAX_DATABASE_SQL_LENGTH, L"ATTACH DATABASE '%s' AS encrypted KEY '%s'", pPhysicalDbPath.get(), pDbKey.get());
1600
1601         sql.Append(*pSqlStr);
1602         r = pDatabase->ExecuteSql(sql, true);
1603         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1604         sql.Clear();
1605
1606         unique_ptr<DbEnumerator> pEnum(pDatabase->QueryN(L"SELECT sql FROM (SELECT * FROM sqlite_master UNION ALL  SELECT * FROM sqlite_temp_master) WHERE type!='meta' ORDER BY tbl_name, type DESC, name"));
1607         r = GetLastResult();
1608         if (r == E_SUCCESS)
1609         {
1610                 if (pEnum)
1611                 {
1612                         String schema;
1613                         String tempQuery(L"encrypted.");
1614
1615                         while (pEnum->MoveNext() == E_SUCCESS)
1616                         {
1617                                 r = pEnum->GetStringAt(0, schema);
1618                                 if (r != E_SUCCESS)
1619                                 {
1620                                         if (r == E_INVALID_STATE || r == E_TYPE_MISMATCH || r == E_INVALID_ENCODING_RANGE) //internal exception by this method
1621                                         {
1622                                                 r = E_SYSTEM;
1623                                         }
1624                                         return r;
1625                                 }
1626
1627                                 if (schema.StartsWith(L"sqlite_", MAX_SQLCIPHER_SCHEMA_PREFIX_SIZE))
1628                                 {
1629                                         continue;
1630                                 }
1631
1632                                 r = schema.Insert(tempQuery, MAX_SQLCIPHER_SCHEMA_PREFIX_SIZE);
1633                                 if (IsFailed(r))
1634                                 {
1635                                         return E_SYSTEM;
1636                                 }
1637
1638                                 r = pDatabase->ExecuteSql(schema, true);
1639                                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to caller...", GetErrorMessage(r));
1640                         }
1641                 }
1642         }
1643         else
1644         {
1645                 SysPropagate(NID_IO, r);
1646                 return r;
1647         }
1648
1649         pEnum.reset(pDatabase->QueryN(L"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"));
1650         r = GetLastResult();
1651         if (r == E_SUCCESS)
1652         {
1653                 if (pEnum)
1654                 {
1655                         String tableName;
1656                         while (pEnum->MoveNext() == E_SUCCESS)
1657                         {
1658                                 r = pEnum->GetStringAt(0, tableName);
1659                                 if (r != E_SUCCESS)
1660                                 {
1661                                         if (r == E_INVALID_STATE || r == E_TYPE_MISMATCH || r == E_INVALID_ENCODING_RANGE) //internal exception by this method
1662                                         {
1663                                                 r = E_IO;
1664                                         }
1665
1666                                         return r;
1667                                 }
1668
1669                                 if (tableName.StartsWith(L"sqlite_", 0))
1670                                 {
1671                                         continue;
1672                                 }
1673
1674                                 pSqlStr.reset(new (std::nothrow) String(MAX_DATABASE_SQL_LENGTH));
1675                                 SysTryReturnResult(NID_IO, pSqlStr, E_OUT_OF_MEMORY, "The memory is insufficient.");
1676
1677                                 pSqlStr->Format(MAX_DATABASE_SQL_LENGTH, L"INSERT INTO encrypted.%ls SELECT * FROM %ls", tableName.GetPointer(), tableName.GetPointer());
1678
1679                                 sql.Append(*pSqlStr);
1680                                 r = pDatabase->ExecuteSql(sql, true);
1681                                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1682                                 sql.Clear();
1683                         }
1684                 }
1685         }
1686         else
1687         {
1688                 SysPropagate(NID_IO, r);
1689                 return r;
1690         }
1691
1692         sql.Append(L"DETACH DATABASE encrypted");
1693
1694         r = pDatabase->ExecuteSql(sql, true);
1695         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1696
1697         return E_SUCCESS;
1698 }
1699
1700 _DatabaseImpl*
1701 _DatabaseImpl::GetInstance(Database& database)
1702 {
1703         return database.__pDatabaseImpl;
1704 }
1705
1706 const _DatabaseImpl*
1707 _DatabaseImpl::GetInstance(const Database& database)
1708 {
1709         return database.__pDatabaseImpl;
1710 }
1711
1712 }} // Tizen::Io
1713