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