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