2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @file FIo_DatabaseImpl.cpp
19 * @brief This is the implementation file for _DatabaseImpl class.
25 #include <semaphore.h>
30 #include <unique_ptr.h>
34 #include <FBaseResult.h>
35 #include <FBaseSysLog.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>
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>
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;
63 namespace Tizen { namespace Io
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.
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";
78 _DatabaseImpl::_DatabaseImpl(void)
80 , __transactionGoingOn(false)
84 _DatabaseImpl::~_DatabaseImpl(void)
87 sqlite3_stmt* pSqlStmt = null;
91 pSqlStmt = sqlite3_next_stmt((sqlite3*) __pDatabase, 0);
92 while (pSqlStmt != null)
94 sqlite3_finalize(pSqlStmt);
95 pSqlStmt = sqlite3_next_stmt((sqlite3*) __pDatabase, 0);
98 int ret = sqlite3_close((sqlite3*) __pDatabase);
101 r = __ConvertNativeSqliteErrorToResult(ret);
102 SysLog(NID_IO, "[%s] ERROR Message: [%s], Failed to close database.", GetErrorMessage(r),
103 sqlite3_errmsg((sqlite3*) __pDatabase));
108 __transactionGoingOn = false;
112 // release user context info
113 __userFunctionContextList.RemoveAll(true);
114 __userCollationContextList.RemoveAll(true);
119 _DatabaseImpl::IsDirectory(const String& databasePath)
122 result r = E_SUCCESS;
124 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(databasePath, _AppInfo::IsOspCompat()) == true,
125 E_INVALID_ARG, " [%ls] is not compatible.", databasePath.GetPointer());
127 r = _FileImpl::GetAttributes(databasePath, attr);
134 SetLastResult(E_SUCCESS);
135 return attr.IsDirectory();
139 _DatabaseImpl::VerifyDatabaseOpenMode(const char* pOpenMode, long& legacyMode)
141 if (pOpenMode == null)
143 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode is null.");
147 if (strlen(pOpenMode) > _MAX_DB_OPENMODE_LENGTH)
149 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
153 if (pOpenMode[0] == 'r')
155 if (pOpenMode[1] == '\0')
157 legacyMode = DB_OPEN_READ_ONLY;
159 else if (pOpenMode[1] == '+')
161 if (pOpenMode[2] == '\0')
163 legacyMode = DB_OPEN_READ_WRITE;
167 else if (pOpenMode[0] == 'a' && pOpenMode[1] == '+' && pOpenMode[2] == '\0')
169 legacyMode = (DB_OPEN_CREATE | DB_OPEN_READ_WRITE);
173 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
181 _DatabaseImpl::Construct(const String& dbPath, bool createIfNotExist)
183 long openMode = DB_OPEN_READ_WRITE;
185 if (!_FileImpl::IsFileExist(dbPath))
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;
192 return Construct(dbPath, openMode, null);
196 _DatabaseImpl::Construct(const String& dbPath, long openMode, const ByteBuffer* pSecretKey)
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.");
204 result r = E_SUCCESS;
208 bool isFilePathExist = false;
209 bool isParentDirPathExist = false;
211 String parentDirPath;
215 case (DB_OPEN_READ_WRITE):
216 openFlags = SQLITE_OPEN_READWRITE;
219 case (DB_OPEN_READ_ONLY):
220 openFlags = SQLITE_OPEN_READONLY;
223 case (DB_OPEN_READ_WRITE | DB_OPEN_CREATE):
224 openFlags = (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
228 SysLog(NID_IO, "[E_INVALID_ARG] The specified open mode flags are invalid.");
229 return E_INVALID_ARG;
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.");
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.");
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.");
249 unique_ptr<char[]> pDbPath(_StringConverter::CopyToCharArrayN(dbPath));
251 SysTryCatch(NID_IO, pDbPath, , r, "[%s] pDbPath is null.", GetErrorMessage(r));
253 // check existence of file
254 isFilePathExist = _FileImpl::IsFileExist(dbPath);
255 if (isFilePathExist == true)
257 if (openMode == (DB_OPEN_READ_WRITE | DB_OPEN_CREATE))
259 SysLog(NID_IO, "[E_FILE_ALREADY_EXIST] File already exists.");
260 r = E_FILE_ALREADY_EXIST;
264 //check if it is a directory
265 if (IsDirectory(dbPath))
267 SysLog(NID_IO, "[E_DATABASE] Given path is not a File.");
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.");
277 if (pSecretKey && _SecureIoUtil::IsNormalDatabase(dbMode))
279 SysTryCatch(NID_IO, false, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Trying to open a normal database in secure mode.");
281 else if (!pSecretKey && _SecureIoUtil::IsSecureDatabase(dbMode))
283 SysTryCatch(NID_IO, false, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Trying to open a secure database in normal mode.");
293 if (openMode == DB_OPEN_READ_WRITE || openMode == DB_OPEN_READ_ONLY)
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;
301 // open/create the database
302 ret = sqlite3_open_v2(pDbPath.get(), &pDb, openFlags, null);
303 if (ret != SQLITE_OK)
305 r = __ConvertNativeSqliteErrorToResult(ret);
306 SysLog(NID_IO, "[%s] sqlite3_open_v2() failed (%d, %s).", GetErrorMessage(r), ret, sqlite3_errmsg(pDb));
312 unique_ptr<byte[]> pDbKey(_SecureIoUtil::GenerateDatabaseKeyN(pSecretKey));
313 SysTryReturnResult(NID_IO, pDbKey != null, E_IO, "GenerateDatabaseKeyN returned null.");
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.");
321 ret = sqlite3_key(pDb, pDbKey.get(), MAX_DATABASE_AES_KEY_LENGTH * 2);
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());
328 sqlite3_key_func = reinterpret_cast< int (*)(sqlite3*, const void*, int) >(dlsym(handle, _DATABASE_ENCRYPTION_SYMBOL));
329 if (sqlite3_key_func == null)
331 SysLog(NID_IO, "This operation is not supported. (%s)", dlerror());
333 r = E_UNSUPPORTED_OPERATION;
337 ret = sqlite3_key_func(pDb, pDbKey.get(), MAX_DATABASE_AES_KEY_LENGTH * 2);
340 if (ret != SQLITE_OK)
342 r = __ConvertNativeSqliteErrorToResult(ret);
343 SysLog(NID_IO, "[%s] sqlite3_key() failed (%d, %s).", GetErrorMessage(r), ret, sqlite3_errmsg(pDb));
358 _DatabaseImpl::Construct(const String& dbPath, const char* pOpenMode, const ByteBuffer* pSecretKey)
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.");
367 bool isValidOpenMode = _DatabaseImpl::VerifyDatabaseOpenMode(pOpenMode, legacyMode);
368 SysTryReturnResult(NID_IO, isValidOpenMode == true, E_INVALID_ARG, "The specified openMode is invalid. (%s)", pOpenMode);
373 bool isFilePathExist = false;
374 bool isParentDirPathExist = false;
376 String parentDirPath;
380 case DB_OPEN_READ_WRITE:
381 openFlags = SQLITE_OPEN_READWRITE;
383 case DB_OPEN_READ_ONLY:
384 openFlags = SQLITE_OPEN_READONLY;
386 case (DB_OPEN_READ_WRITE | DB_OPEN_CREATE):
387 openFlags = (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
390 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
391 return E_INVALID_ARG;
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.");
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.");
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.");
411 unique_ptr<char[]> pDbPath(_StringConverter::CopyToCharArrayN(dbPath));
412 SysTryReturn(NID_IO, pDbPath, GetLastResult(), GetLastResult(), "[%s] pDbPath is null.", GetErrorMessage(GetLastResult()));
414 //check existence of file
415 isFilePathExist = _FileImpl::IsFileExist(dbPath);
416 if (isFilePathExist == true)
418 //check if it is a directory
419 SysTryReturnResult(NID_IO, !IsDirectory(dbPath), E_INVALID_ARG, "Given path is not a File.");
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.");
427 if (pSecretKey && _SecureIoUtil::IsNormalDatabase(dbMode))
429 SysTryReturnResult(NID_IO, false, E_INVALID_ARG,
430 "Trying to open a normal database in secure mode.");
432 else if (!pSecretKey && _SecureIoUtil::IsSecureDatabase(dbMode))
434 SysTryReturnResult(NID_IO, false, E_INVALID_ARG,
435 "Trying to open a secure database in normal mode.");
445 if (legacyMode == DB_OPEN_READ_WRITE || legacyMode == DB_OPEN_READ_ONLY)
447 SysLog(NID_IO, "[E_FILE_NOT_FOUND] File not found.");
448 r = E_FILE_NOT_FOUND;
453 // open/create the database
454 ret = sqlite3_open_v2(pDbPath.get(), &pDb, openFlags, null);
455 if (ret != SQLITE_OK)
457 if (!_AppInfo::IsOspCompat())
459 r = __ConvertNativeSqliteErrorToDetailResult(ret);
463 case E_OBJECT_LOCKED:
464 case E_INVALID_OPERATION:
472 r = __ConvertNativeSqliteErrorToResult(ret);
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)));
482 unique_ptr<byte[]> pDbKey(_SecureIoUtil::GenerateDatabaseKeyN(pSecretKey));
483 SysTryReturnResult(NID_IO, pDbKey != null, E_IO, "GenerateDatabaseKeyN returned null.");
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.");
491 ret = sqlite3_key(pDb, pDbKey.get(), MAX_DATABASE_AES_KEY_LENGTH * 2);
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());
498 sqlite3_key_func = reinterpret_cast< int (*)(sqlite3*, const void*, int) >(dlsym(handle, _DATABASE_ENCRYPTION_SYMBOL));
499 if (sqlite3_key_func == null)
501 SysLog(NID_IO, "This operation is not supported. (%s)", dlerror());
503 r = E_UNSUPPORTED_OPERATION;
507 ret = sqlite3_key_func(pDb, pDbKey.get(), MAX_DATABASE_AES_KEY_LENGTH * 2);
510 if (ret != SQLITE_OK)
512 if (!_AppInfo::IsOspCompat())
521 SysLog(NID_IO, "[%s] Failed to create secret key (%d, %s).", GetErrorMessage(r), ret,
522 sqlite3_errmsg(static_cast< sqlite3* >(pDb)));
537 _DatabaseImpl::CreateStatementN(const String& statement)
539 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
542 char* pStrStmt = null;
543 sqlite3_stmt* pSqlStmt = null;
544 result r = E_SUCCESS;
546 unique_ptr<DbStatement> pDbStatement(_DbStatementImpl::CreateDbStatementInstanceN());
548 SysTryReturn(NID_IO, pDbStatement != null, null, E_OUT_OF_MEMORY,
549 "[E_OUT_OF_MEMORY] The memory is insufficient.");
551 unique_ptr<char[]> pUnTrimStatement(_StringConverter::CopyToCharArrayN(statement));
552 if (pUnTrimStatement == null)
558 // trim leading spaces
559 pStrStmt = pUnTrimStatement.get();
560 while ((*pStrStmt == ' ') || (*pStrStmt == '\t'))
565 // prepare the sql statement
566 ret = sqlite3_prepare_v2((sqlite3*) __pDatabase, pStrStmt, strlen(pStrStmt), &pSqlStmt, null);
567 if (ret != SQLITE_OK)
569 if (!_AppInfo::IsOspCompat())
571 r = __ConvertNativeSqliteErrorToDetailResult(ret);
574 case E_ILLEGAL_ACCESS:
576 case E_INVALID_FORMAT:
578 case E_INVALID_OPERATION:
586 r = __ConvertNativeSqliteErrorToResult(ret);
589 SysLog(NID_IO, "[%s] Failed to prepare SQL statement (%s). (%d, %s).", GetErrorMessage(r), pStrStmt,
590 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
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;
599 if (strncasecmp(pStrStmt, "select", 6) == 0)
601 _DbStatementImpl::GetInstance(*pDbStatement)->__stmtType = DB_STATEMENT_TYPE_SELECT;
605 _DbStatementImpl::GetInstance(*pDbStatement)->__stmtType = DB_STATEMENT_TYPE_OTHER;
609 return pDbStatement.release();
617 _DatabaseImpl::ExecuteStatementN(const DbStatement& statement)
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)");
624 DbEnumerator* pDbEnum = null;
625 result r = E_SUCCESS;
627 ret = sqlite3_reset((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
628 if (ret != SQLITE_OK)
630 if (!_AppInfo::IsOspCompat())
632 r = __ConvertNativeSqliteErrorToDetailResult(ret);
636 case E_ILLEGAL_ACCESS:
638 case E_INVALID_FORMAT:
640 case E_INVALID_OPERATION:
648 r = __ConvertNativeSqliteErrorToResult(ret);
651 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
652 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
657 ret = sqlite3_step((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
662 ret = sqlite3_reset((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
663 if (ret != SQLITE_OK)
665 if (!_AppInfo::IsOspCompat())
667 r = __ConvertNativeSqliteErrorToDetailResult(ret);
671 case E_ILLEGAL_ACCESS:
673 case E_INVALID_FORMAT:
675 case E_INVALID_OPERATION:
683 r = __ConvertNativeSqliteErrorToResult(ret);
686 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
687 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
693 if (_DbStatementImpl::GetInstance(statement)->__stmtType == DB_STATEMENT_TYPE_SELECT)
695 unique_ptr<DbEnumerator> pTempDbEnum(_DbEnumeratorImpl::CreateDbEnumeratorInstanceN());
697 SysTryReturn(NID_IO, pTempDbEnum != null, null, E_OUT_OF_MEMORY,
698 "[E_OUT_OF_MEMORY] The memory is insufficient.");
700 _DbEnumeratorImpl::GetInstance(*pTempDbEnum)->__pEnum = _DbStatementImpl::GetInstance(statement)->__pStmt;
701 _DbEnumeratorImpl::GetInstance(*pTempDbEnum)->__pDatabase = _DbStatementImpl::GetInstance(statement)->__pDatabase;
704 ret = sqlite3_reset((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
705 if (ret != SQLITE_OK)
707 if (!_AppInfo::IsOspCompat())
709 r = __ConvertNativeSqliteErrorToDetailResult(ret);
713 case E_ILLEGAL_ACCESS:
715 case E_INVALID_FORMAT:
717 case E_INVALID_OPERATION:
725 r = __ConvertNativeSqliteErrorToResult(ret);
728 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
729 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
734 pDbEnum = pTempDbEnum.release();
739 goto REDO_SQLITE_STEP;
744 if (!_AppInfo::IsOspCompat())
746 r = __ConvertNativeSqliteErrorToDetailResult(ret);
749 case E_ILLEGAL_ACCESS:
750 case E_INVALID_OPERATION:
758 r = __ConvertNativeSqliteErrorToResult(ret);
761 SysLog(NID_IO, "[%s] Failed to execute SQL statement. (%d, %s).", GetErrorMessage(r), ret,
762 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
766 SetLastResult(E_SUCCESS);
775 _DatabaseImpl::ExecuteSql(const String& sql, bool autoCommit)
777 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
780 char* pSqlStr = null;
781 result r = E_SUCCESS;
783 unique_ptr<char[]> pUnTrimStatement(_StringConverter::CopyToCharArrayN(sql));
784 if (pUnTrimStatement == null)
790 // trim leading spaces
791 pSqlStr = pUnTrimStatement.get();
792 while ((*pSqlStr == ' ') || (*pSqlStr == '\t'))
797 if (strncasecmp(pSqlStr, "select", 6) == 0)
799 r = E_INVALID_OPERATION;
803 ret = sqlite3_exec((sqlite3*) __pDatabase, pSqlStr, null, null, null);
804 if (ret != SQLITE_OK)
806 if (!_AppInfo::IsOspCompat())
808 r = __ConvertNativeSqliteErrorToDetailResult(ret);
811 case E_ILLEGAL_ACCESS:
812 case E_INVALID_OPERATION:
820 r = __ConvertNativeSqliteErrorToResult(ret);
823 SysLog(NID_IO, "[%s] Failed to execute SQL statement. (%d, %s).", GetErrorMessage(r), ret,
824 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
835 _DatabaseImpl::QueryN(const String& query)
837 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
841 sqlite3_stmt* pSqlStmt = null;
842 unique_ptr<DbEnumerator> pDbEnum(null);
843 result r = E_SUCCESS;
845 unique_ptr<char[]> pUnTrimStatement(_StringConverter::CopyToCharArrayN(query));
846 if (pUnTrimStatement == null)
852 // trim leading spaces
853 pQuery = pUnTrimStatement.get();
854 while ((*pQuery == ' ') || (*pQuery == '\t'))
859 if ((strncasecmp(pQuery, "select", 6) != 0) && (strncasecmp(pQuery, "PRAGMA", 6) != 0))
861 r = E_INVALID_OPERATION;
865 // prepare the sql statement
866 ret = sqlite3_prepare_v2((sqlite3*) __pDatabase, pQuery, strlen(pQuery), &pSqlStmt, null);
867 if (ret != SQLITE_OK)
869 if (!_AppInfo::IsOspCompat())
871 r = __ConvertNativeSqliteErrorToDetailResult(ret);
874 case E_ILLEGAL_ACCESS:
876 case E_INVALID_FORMAT:
878 case E_INVALID_OPERATION:
886 r = __ConvertNativeSqliteErrorToResult(ret);
889 SysLog(NID_IO, "[%s] Failed to prepare SQL statement (%s). (%d, %s).", GetErrorMessage(r), pQuery,
890 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
894 // ret = sqlite3_reset((sqlite3_stmt *) pSqlStmt);
895 // if (ret != SQLITE_OK)
897 // r = __ConvertNativeSqliteErrorToResult(ret);
898 // SysLog(NID_IO, "[_DatabaseImpl] ERROR: [%s] Failed to reset SQL statement.", GetErrorMessage(r));
902 ret = sqlite3_step(pSqlStmt);
910 pDbEnum.reset(_DbEnumeratorImpl::CreateDbEnumeratorInstanceN());
912 SysTryCatch(NID_IO, pDbEnum != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
913 "[E_OUT_OF_MEMORY] The memory is insufficient.");
915 _DbEnumeratorImpl::GetInstance(*pDbEnum)->__pEnum = pSqlStmt;
916 _DbEnumeratorImpl::GetInstance(*pDbEnum)->__pDatabase = __pDatabase;
917 _DbEnumeratorImpl::GetInstance(*pDbEnum)->__shouldReleaseResource = true;
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)
923 if (!_AppInfo::IsOspCompat())
925 r = __ConvertNativeSqliteErrorToDetailResult(ret);
929 case E_ILLEGAL_ACCESS:
931 case E_INVALID_FORMAT:
933 case E_INVALID_OPERATION:
941 r = __ConvertNativeSqliteErrorToResult(ret);
944 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
945 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
951 if (!_AppInfo::IsOspCompat())
953 r = __ConvertNativeSqliteErrorToDetailResult(ret);
956 case E_ILLEGAL_ACCESS:
958 case E_INVALID_OPERATION:
966 r = __ConvertNativeSqliteErrorToResult(ret);
969 SysLog(NID_IO, "[%s] Failed to exectue SQL statement (%s). (%d, %s).", GetErrorMessage(r), pQuery,
970 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
975 return pDbEnum.release();
978 sqlite3_finalize(pSqlStmt);
984 _DatabaseImpl::BeginTransaction(void)
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.");
990 result r = E_SUCCESS;
992 if (sqlite3_get_autocommit((sqlite3*) __pDatabase) == 0)
994 SysLog(NID_IO, "[E_INVALID_STATE] Already in transaction mode.");
995 return E_INVALID_STATE;
998 int ret = sqlite3_exec((sqlite3*) __pDatabase, "BEGIN", null, null, null);
999 if (ret != SQLITE_OK)
1001 if (!_AppInfo::IsOspCompat())
1003 r = __ConvertNativeSqliteErrorToDetailResult(ret);
1007 case E_ILLEGAL_ACCESS:
1008 case E_OBJECT_LOCKED:
1010 case E_INVALID_FORMAT:
1011 case E_STORAGE_FULL:
1012 case E_INVALID_OPERATION:
1019 r = __ConvertNativeSqliteErrorToResult(ret);
1022 SysLog(NID_IO, "[%s] Failed to begin transaction. (%d, %s)", GetErrorMessage(r), ret,
1023 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
1027 __transactionGoingOn = true;
1034 _DatabaseImpl::CommitTransaction(void)
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.");
1041 result r = E_SUCCESS;
1043 if (sqlite3_get_autocommit((sqlite3*) __pDatabase) != 0)
1045 SysLog(NID_IO, "[E_INVALID_STATE] ERROR Message: Not in transaction mode.");
1046 return E_INVALID_STATE;
1049 ret = sqlite3_exec((sqlite3*) __pDatabase, "COMMIT", null, null, null);
1050 if (ret != SQLITE_OK)
1052 if (!_AppInfo::IsOspCompat())
1054 r = __ConvertNativeSqliteErrorToDetailResult(ret);
1058 case E_ILLEGAL_ACCESS:
1059 case E_INVALID_OPERATION:
1066 r = __ConvertNativeSqliteErrorToResult(ret);
1069 SysLog(NID_IO, "[%s] Failed to commit transaction. (%d, %s)", GetErrorMessage(r), ret,
1070 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
1074 __transactionGoingOn = false;
1081 _DatabaseImpl::RollbackTransaction(void)
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.");
1088 result r = E_SUCCESS;
1090 if (sqlite3_get_autocommit((sqlite3*) __pDatabase) != 0)
1092 SysLog(NID_IO, "[E_SUCCESS] No transaction in progress.");
1093 //return E_INVALID_STATE;
1097 ret = sqlite3_exec((sqlite3*) __pDatabase, "ROLLBACK", null, null, null);
1098 if (ret != SQLITE_OK)
1100 if (!_AppInfo::IsOspCompat())
1102 r = __ConvertNativeSqliteErrorToDetailResult(ret);
1106 case E_ILLEGAL_ACCESS:
1107 case E_INVALID_OPERATION:
1114 r = __ConvertNativeSqliteErrorToResult(ret);
1117 SysLog(NID_IO, "[%s] Failed to rollback the transaction. (%d, %s)", GetErrorMessage(r), ret,
1118 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
1122 __transactionGoingOn = false;
1129 _DatabaseImpl::GetName(void) const
1131 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1133 SetLastResult(E_SUCCESS);
1138 _DatabaseImpl::RegisterUserFunction(const String& functionName, const int argumentCount, void* pUserData,
1139 _IDbUserFunctionListener* pUserFunctionListener,
1140 _IDbUserAggregateListener* pUserAggregateListener)
1142 result r = E_SUCCESS;
1143 int sqliteEncoding = 0;
1146 unique_ptr<_DbContextImpl> pDbContext(null);
1147 _DbContextImpl* pTempDbContext = null;
1148 bool entryFound = false;
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.");
1158 if (pUserFunctionListener != null && pUserAggregateListener != null)
1160 SysTryReturnResult(NID_IO, 0, E_INVALID_ARG,
1161 "FunctionListener and AggregateListener cannot be registered together");
1164 //select the equivalent sqlite encoding.
1166 unique_ptr<ByteBuffer> pFuncNameBuf(StringUtil::StringToUtf8N(functionName));
1167 SysTryReturn(NID_IO, pFuncNameBuf != null, GetLastResult(),
1168 GetLastResult(), "[%s] Invalid Function name.", GetErrorMessage(GetLastResult()));
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.");
1174 sqliteEncoding = SQLITE_UTF8; // support only UTF8
1176 //check if the (FunctionName, argumentCount) already exist in the list
1177 for (i = 0; i < __userFunctionContextList.GetCount(); i++)
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))
1189 if (entryFound && (null != pUserFunctionListener || null != pUserAggregateListener))
1191 SysTryReturnResult(NID_IO, 0, E_INVALID_ARG,
1192 "(functionName, argumentCount) already registered");
1195 if (pUserFunctionListener != null) // register FunctionListener
1197 pDbContext.reset(new (std::nothrow) _DbContextImpl());
1198 SysTryReturnResult(NID_IO, pDbContext != null, E_OUT_OF_MEMORY,
1199 "The memory is insufficient.");
1201 ret = sqlite3_create_function((sqlite3*) __pDatabase,
1202 (const char*) pFuncNameBuf->GetPointer(), argumentCount, sqliteEncoding, pDbContext.get(),
1203 _DatabaseImpl::UserFunctionListener, null, null);
1205 else if (pUserAggregateListener != null) // register both FunctionStepListener and FunctionFinalListener
1207 pDbContext.reset(new (std::nothrow) _DbContextImpl());
1209 SysTryReturnResult(NID_IO, pDbContext != null, E_OUT_OF_MEMORY,
1210 "The memory is insufficient.");
1212 ret = sqlite3_create_function((sqlite3*) __pDatabase,
1213 (const char*) pFuncNameBuf->GetPointer(), argumentCount, sqliteEncoding, pDbContext.get(),
1214 null, _DatabaseImpl::UserFunctionStepListener, _DatabaseImpl::UserFunctionFinalListener);
1216 else // Delete registered user function/Aggregate
1218 ret = sqlite3_create_function((sqlite3*) __pDatabase,
1219 (const char*) pFuncNameBuf->GetPointer(), argumentCount, sqliteEncoding, null, null, null, null);
1222 if (ret != SQLITE_OK) //error
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));
1230 if (entryFound && (!pUserFunctionListener && !pUserAggregateListener)) // delete the user function entry from list
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()));
1237 if (pDbContext != null)
1239 //store listener and user data
1240 pDbContext->__pUserData = pUserData;
1241 pDbContext->__argumentCount = argumentCount;
1242 pDbContext->__functionName = functionName;
1243 if (pUserFunctionListener != null)
1245 pDbContext->__pUserFunctionListener = pUserFunctionListener;
1247 if (pUserAggregateListener != null)
1249 pDbContext->__pUserAggregateListener = pUserAggregateListener;
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()));
1262 _DatabaseImpl::RegisterUserCollation(const String& collationName, void* pUserData,
1263 _IDbUserCollationListener* pUserCollationListener)
1265 result r = E_SUCCESS;
1266 int sqliteEncoding = 0;
1269 unique_ptr<_DbContextImpl> pDbContext(null);
1270 _DbContextImpl* pTempDbContext = null;
1271 bool entryFound = false;
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.");
1278 sqliteEncoding = SQLITE_UTF8; // support only UTF8
1280 unique_ptr<ByteBuffer> pColNameBuf(StringUtil::StringToUtf8N(collationName));
1281 SysTryReturn(NID_IO, pColNameBuf != null, GetLastResult(), GetLastResult(), "[%s] Invalid Function name.",
1282 GetErrorMessage(GetLastResult()));
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.");
1288 //check if the (FunctionName) already registered
1289 for (i = 0; i < __userCollationContextList.GetCount(); i++)
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)
1300 if (entryFound && (pUserCollationListener != null)) // check if the operation is to delete the user function
1302 SysTryReturnResult(NID_IO, 0, E_INVALID_ARG, "(collationName) already registered");
1305 if (pUserCollationListener != null)
1307 pDbContext.reset(new (std::nothrow) _DbContextImpl());
1308 SysTryReturnResult(NID_IO, pDbContext != null, E_OUT_OF_MEMORY,
1309 "The memory is insufficient.");
1311 // register CollationListener()
1312 ret = sqlite3_create_collation((sqlite3*) __pDatabase, (const char*) pColNameBuf->GetPointer(), sqliteEncoding, pDbContext.get(),
1313 _DatabaseImpl::UserCollationListener);
1315 else // delete Collating function
1317 ret = sqlite3_create_collation((sqlite3*) __pDatabase, (const char*) pColNameBuf->GetPointer(), sqliteEncoding, null, null);
1320 if (ret != SQLITE_OK)
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));
1328 if (entryFound && !pUserCollationListener) // delete the user collation entry from list
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()));
1335 if (pDbContext != null)
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()));
1352 _DatabaseImpl::GetLastInsertRowId(void) const
1354 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
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)
1372 _DatabaseImpl::Delete(const String& databasePath)
1374 result r = E_SUCCESS;
1377 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(databasePath, _AppInfo::IsOspCompat()) == true,
1378 E_INVALID_ARG, " [%ls] is not compatible.", databasePath.GetPointer());
1380 unique_ptr<char[]> pDbPath(_StringConverter::CopyToCharArrayN(databasePath));
1381 if (pDbPath == null)
1383 return GetLastResult();
1387 ret = unlink(pDbPath.get());
1390 r = __ConvertNativeErrorToResult(errno);
1397 _DatabaseImpl::Exists(const String& databasePath)
1399 return _FileImpl::IsFileExist(databasePath);
1403 _DatabaseImpl::UserFunctionListener(sqlite3_context* pContext, int argumentCount, sqlite3_value** pArgList)
1405 _DbContextImpl* pDbContext = null;
1407 pDbContext = static_cast< _DbContextImpl* >(sqlite3_user_data(pContext));
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.");
1413 //Set DbContext data
1414 if (pDbContext->__pContext != (void*) pContext)
1416 pDbContext->__pContext = (void*) pContext;
1419 if (pDbContext->__argumentCount != argumentCount)
1421 SysLog(NID_IO, "Message: __argumentCount mismatch.");
1422 pDbContext->__argumentCount = argumentCount;
1425 if (pDbContext->__pArgList != (void**) pArgList)
1427 pDbContext->__pArgList = (void**) pArgList;
1429 // Invoke the user listener method
1430 pDbContext->__pUserFunctionListener->OnDbUserFunction(*pDbContext, argumentCount);
1432 SetLastResult(E_SUCCESS);
1436 _DatabaseImpl::UserFunctionStepListener(sqlite3_context* pContext, int argumentCount, sqlite3_value** pArgList)
1438 _DbContextImpl* pDbContext = null;
1440 pDbContext = static_cast< _DbContextImpl* >(sqlite3_user_data(pContext));
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.");
1446 //Set DbContext data
1447 if (pDbContext->__pContext != (void*) pContext)
1449 pDbContext->__pContext = (void*) pContext;
1452 if (pDbContext->__argumentCount != argumentCount)
1454 pDbContext->__argumentCount = argumentCount;
1457 if (pDbContext->__pArgList != (void**) pArgList)
1459 pDbContext->__pArgList = (void**) pArgList;
1462 // invoke the user listener method
1463 pDbContext->__pUserAggregateListener->OnDbUserAggregateStep(*pDbContext, argumentCount);
1465 SetLastResult(E_SUCCESS);
1469 _DatabaseImpl::UserFunctionFinalListener(sqlite3_context* pContext)
1471 _DbContextImpl* pDbContext = null;
1473 pDbContext = static_cast< _DbContextImpl* >(sqlite3_user_data(pContext));
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.");
1479 // set context and user data
1480 if (pDbContext->__pContext != (void*) pContext)
1482 pDbContext->__pContext = (void*) pContext;
1485 // invoke the user listener method
1486 pDbContext->__pUserAggregateListener->OnDbUserAggregateFinal(*pDbContext);
1488 SetLastResult(E_SUCCESS);
1492 _DatabaseImpl::UserCollationListener(void* pUserData, int length1, const void* pInput1, int length2, const void* pInput2)
1494 _DbContextImpl* pDbContext = null;
1495 char* pDataInput = null;
1499 pDbContext = static_cast< _DbContextImpl* >(pUserData);
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.");
1505 if (length1 > 0 && (const char*) pInput1 != null)
1507 pDataInput = (char*) malloc((length1 + 1) * sizeof(char));
1509 if (pDataInput == null)
1514 memset(pDataInput, 0, length1 + 1);
1515 strncpy(pDataInput, (const char*) pInput1, length1);
1517 string1.Append((const char*) pDataInput);
1521 if (length2 > 0 && (const char*) pInput2 != null)
1523 pDataInput = (char*) malloc((length2 + 1) * sizeof(char));
1525 if (pDataInput == null)
1530 memset(pDataInput, 0, length2 + 1);
1531 strncpy(pDataInput, (const char*) pInput2, length2);
1533 string2.Append((const char*) pDataInput);
1537 SetLastResult(E_SUCCESS);
1539 return pDbContext->__pUserCollationListener->OnDbUserCollation(string1, string2, pUserData);
1543 _DatabaseImpl::ConvertToSecureDatabase(const String& plainDbPath, const String& secureDbPath, const ByteBuffer* pKey)
1545 result r = E_SUCCESS;
1547 String parentDirPath;
1548 FileAttributes attr;
1550 if (Database::Exists(secureDbPath))
1552 if (GetLastResult() == E_SUCCESS)
1554 r = File::GetAttributes(secureDbPath, attr);
1557 if (attr.IsDirectory())
1559 return E_INVALID_ARG;
1563 return E_FILE_ALREADY_EXIST;
1577 unique_ptr<Database>pDatabase(new (std::nothrow) Database());
1578 SysTryReturnResult(NID_IO, pDatabase, E_OUT_OF_MEMORY, "The memory is insufficient.");
1580 r = pDatabase->Construct(secureDbPath, "a+");
1581 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1583 pDatabase.reset(new (std::nothrow) Database());
1584 SysTryReturnResult(NID_IO, pDatabase, E_OUT_OF_MEMORY, "The memory is insufficient.");
1586 r = pDatabase->Construct(plainDbPath, "r+");
1587 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
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.");
1592 unique_ptr<char[]> pPhysicalDbPath(_StringConverter::CopyToCharArrayN(secureDbPath));
1593 SysTryReturn(NID_IO, pPhysicalDbPath != null, GetLastResult(), GetLastResult(), "[%s] Invalid file path.", GetErrorMessage(GetLastResult()));
1595 unique_ptr<byte[]> pDbKey(_SecureIoUtil::GenerateDatabaseKeyN(pKey));
1596 SysTryReturnResult(NID_IO, pDbKey != null, E_INVALID_ARG, "GenerateDatabaseKeyN returned null.");
1598 pSqlStr->Format(MAX_DATABASE_SQL_LENGTH, L"ATTACH DATABASE '%s' AS encrypted KEY '%s'", pPhysicalDbPath.get(), pDbKey.get());
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));
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();
1612 String tempQuery(L"encrypted.");
1614 while (pEnum->MoveNext() == E_SUCCESS)
1616 r = pEnum->GetStringAt(0, schema);
1619 if (r == E_INVALID_STATE || r == E_TYPE_MISMATCH || r == E_INVALID_ENCODING_RANGE) //internal exception by this method
1626 if (schema.StartsWith(L"sqlite_", MAX_SQLCIPHER_SCHEMA_PREFIX_SIZE))
1631 r = schema.Insert(tempQuery, MAX_SQLCIPHER_SCHEMA_PREFIX_SIZE);
1637 r = pDatabase->ExecuteSql(schema, true);
1638 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to caller...", GetErrorMessage(r));
1644 SysPropagate(NID_IO, r);
1648 pEnum.reset(pDatabase->QueryN(L"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"));
1649 r = GetLastResult();
1655 while (pEnum->MoveNext() == E_SUCCESS)
1657 r = pEnum->GetStringAt(0, tableName);
1660 if (r == E_INVALID_STATE || r == E_TYPE_MISMATCH || r == E_INVALID_ENCODING_RANGE) //internal exception by this method
1668 if (tableName.StartsWith(L"sqlite_", 0))
1673 pSqlStr.reset(new (std::nothrow) String(MAX_DATABASE_SQL_LENGTH));
1674 SysTryReturnResult(NID_IO, pSqlStr, E_OUT_OF_MEMORY, "The memory is insufficient.");
1676 pSqlStr->Format(MAX_DATABASE_SQL_LENGTH, L"INSERT INTO encrypted.%ls SELECT * FROM %ls", tableName.GetPointer(), tableName.GetPointer());
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));
1687 SysPropagate(NID_IO, r);
1691 sql.Append(L"DETACH DATABASE encrypted");
1693 r = pDatabase->ExecuteSql(sql, true);
1694 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1700 _DatabaseImpl::GetInstance(Database& database)
1702 return database.__pDatabaseImpl;
1705 const _DatabaseImpl*
1706 _DatabaseImpl::GetInstance(const Database& database)
1708 return database.__pDatabaseImpl;