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_DATABASE_AES_KEY_LENGTH = 16; //default key size for AES 128
70 const int MAX_DATABASE_SQL_LENGTH = 4096; //buffer length required to make sql query
71 const int MAX_SQLCIPHER_SCHEMA_PREFIX_SIZE = 13;//size of sqlCipher_ schema prefix name.
73 static const size_t _MAX_DB_OPENMODE_LENGTH = 2;
74 static const char _DATABASE_LIBRARY_PATH[] = "/usr/lib/libsqlite3.so.0";
75 static const char _DATABASE_ENCRYPTION_SYMBOL[] = "sqlite3_key";
77 _DatabaseImpl::_DatabaseImpl(void)
79 , __transactionGoingOn(false)
83 _DatabaseImpl::~_DatabaseImpl(void)
86 sqlite3_stmt* pSqlStmt = null;
90 pSqlStmt = sqlite3_next_stmt((sqlite3*) __pDatabase, 0);
91 while (pSqlStmt != null)
93 sqlite3_finalize(pSqlStmt);
94 pSqlStmt = sqlite3_next_stmt((sqlite3*) __pDatabase, 0);
97 int ret = sqlite3_close((sqlite3*) __pDatabase);
100 r = __ConvertNativeSqliteErrorToResult(ret);
101 SysLog(NID_IO, "[%s] ERROR Message: [%s], Failed to close database.", GetErrorMessage(r),
102 sqlite3_errmsg((sqlite3*) __pDatabase));
107 __transactionGoingOn = false;
111 // release user context info
112 __userFunctionContextList.RemoveAll(true);
113 __userCollationContextList.RemoveAll(true);
118 _DatabaseImpl::IsDirectory(const String& databasePath)
121 result r = E_SUCCESS;
123 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(databasePath, _AppInfo::IsOspCompat()) == true,
124 E_INVALID_ARG, " [%ls] is not compatible.", databasePath.GetPointer());
126 r = _FileImpl::GetAttributes(databasePath, attr);
133 SetLastResult(E_SUCCESS);
134 return attr.IsDirectory();
138 _DatabaseImpl::VerifyDatabaseOpenMode(const char* pOpenMode, long& legacyMode)
140 if (pOpenMode == null)
142 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode is null.");
146 if (strlen(pOpenMode) > _MAX_DB_OPENMODE_LENGTH)
148 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
152 if (pOpenMode[0] == 'r')
154 if (pOpenMode[1] == '\0')
156 legacyMode = DB_OPEN_READ_ONLY;
158 else if (pOpenMode[1] == '+')
160 if (pOpenMode[2] == '\0')
162 legacyMode = DB_OPEN_READ_WRITE;
166 else if (pOpenMode[0] == 'a' && pOpenMode[1] == '+' && pOpenMode[2] == '\0')
168 legacyMode = (DB_OPEN_CREATE | DB_OPEN_READ_WRITE);
172 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
180 _DatabaseImpl::Construct(const String& dbPath, bool createIfNotExist)
182 long openMode = DB_OPEN_READ_WRITE;
184 if (!_FileImpl::IsFileExist(dbPath))
186 SysTryReturn(NID_IO, createIfNotExist == true, E_FILE_NOT_FOUND, E_FILE_NOT_FOUND,
187 "[E_FILE_NOT_FOUND] Database file does not exist. Create it first.");
188 openMode = DB_OPEN_READ_WRITE | DB_OPEN_CREATE;
191 return Construct(dbPath, openMode, null);
195 _DatabaseImpl::Construct(const String& dbPath, long openMode, const ByteBuffer* pSecretKey)
197 SysAssertf(__pDatabase == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class\n");
198 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(dbPath, _AppInfo::IsOspCompat()) == true,
199 E_INVALID_ARG, " [%ls] is not compatible.", dbPath.GetPointer());
200 SysTryReturnResult(NID_IO, !(pSecretKey && pSecretKey->GetRemaining() <= 0), E_INVALID_ARG,
201 "The specified secretKey is invalid.");
203 result r = E_SUCCESS;
207 bool isFilePathExist = false;
208 bool isParentDirPathExist = false;
210 String parentDirPath;
214 case (DB_OPEN_READ_WRITE):
215 openFlags = SQLITE_OPEN_READWRITE;
218 case (DB_OPEN_READ_ONLY):
219 openFlags = SQLITE_OPEN_READONLY;
222 case (DB_OPEN_READ_WRITE | DB_OPEN_CREATE):
223 openFlags = (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
227 SysLog(NID_IO, "[E_INVALID_ARG] The specified open mode flags are invalid.");
228 return E_INVALID_ARG;
231 // extract directory path from a given Db file path
232 // Find index of last occurrence of character '/' in dbPath
233 r = dbPath.LastIndexOf(L'/', dbPath.GetLength() - 1, lastIndex);
234 SysTryReturnResult(NID_IO, !IsFailed(r),
235 E_INVALID_ARG, "Missing directory path. SHOULD not happen.");
237 // extract directory path from dbPath starting from index 0 to lastIndex.
238 r = dbPath.SubString(0, lastIndex, parentDirPath);
239 SysTryReturnResult(NID_IO, !IsFailed(r),
240 E_INVALID_ARG, "Missing directory path. SHOULD not happen.");
242 // TODO: Test sqlite3_open_v3() without parent directory.
243 //check existence of parent directory
244 isParentDirPathExist = _FileImpl::IsFileExist(String(parentDirPath));
245 SysTryReturnResult(NID_IO, isParentDirPathExist == true, E_INVALID_ARG,
246 "Parent Directory does not exist.");
248 unique_ptr<char[]> pDbPath(_StringConverter::CopyToCharArrayN(dbPath));
250 SysTryCatch(NID_IO, pDbPath, , r, "[%s] pDbPath is null.", GetErrorMessage(r));
252 // check existence of file
253 isFilePathExist = _FileImpl::IsFileExist(dbPath);
254 if (isFilePathExist == true)
256 if (openMode == (DB_OPEN_READ_WRITE | DB_OPEN_CREATE))
258 SysLog(NID_IO, "[E_FILE_ALREADY_EXIST] File already exists.");
259 r = E_FILE_ALREADY_EXIST;
263 //check if it is a directory
264 if (IsDirectory(dbPath))
266 SysLog(NID_IO, "[E_DATABASE] Given path is not a File.");
272 _DatabaseMode dbMode = DATABASE_MODE_NONE;
273 dbMode = _SecureIoUtil::GetDatabaseMode(pDbPath.get());
274 SysTryCatch(NID_IO, dbMode != DATABASE_MODE_ERROR, r = E_IO, E_IO, "[E_IO] GetDatabaseMode function failed.");
276 if (pSecretKey && _SecureIoUtil::IsNormalDatabase(dbMode))
278 SysTryCatch(NID_IO, false, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Trying to open a normal database in secure mode.");
280 else if (!pSecretKey && _SecureIoUtil::IsSecureDatabase(dbMode))
282 SysTryCatch(NID_IO, false, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Trying to open a secure database in normal mode.");
292 if (openMode == DB_OPEN_READ_WRITE || openMode == DB_OPEN_READ_ONLY)
294 SysLog(NID_IO, "[E_FILE_NOT_FOUND] File not found when opened in DB_OPEN_READ_WRITE/DB_OPEN_READ_ONLY mode.");
295 r = E_FILE_NOT_FOUND;
300 // open/create the database
301 ret = sqlite3_open_v2(pDbPath.get(), &pDb, openFlags, null);
302 if (ret != SQLITE_OK)
304 r = __ConvertNativeSqliteErrorToResult(ret);
305 SysLog(NID_IO, "[%s] sqlite3_open_v2() failed (%d, %s).", GetErrorMessage(r), ret, sqlite3_errmsg(pDb));
311 unique_ptr<byte[]> pDbKey(_SecureIoUtil::GenerateDatabaseKeyN(pSecretKey));
312 SysTryReturnResult(NID_IO, pDbKey != null, E_IO, "GenerateDatabaseKeyN returned null.");
316 r = SystemInfo::GetValue(L"http://tizen.org/feature/database.encryption", secure);
317 SysTryReturnResult(NID_IO, !IsFailed(r), E_SYSTEM, "The method cannot proceed due to a severe system error.");
318 SysTryReturnResult(NID_IO, secure == true, E_UNSUPPORTED_OPERATION, "This operation is not supported.");
320 ret = sqlite3_key(pDb, pDbKey.get(), MAX_DATABASE_AES_KEY_LENGTH * 2);
322 int (* sqlite3_key_func)(sqlite3*, const void*, int) = null;
323 void* handle = dlopen(_DATABASE_LIBRARY_PATH, RTLD_LAZY | RTLD_LOCAL);
324 SysTryReturnResult(NID_IO, handle != null, E_SYSTEM,
325 "Failed to dlopen database library file (%s)", dlerror());
327 sqlite3_key_func = reinterpret_cast< int (*)(sqlite3*, const void*, int) >(dlsym(handle, _DATABASE_ENCRYPTION_SYMBOL));
328 if (sqlite3_key_func == null)
330 SysLog(NID_IO, "This operation is not supported. (%s)", dlerror());
332 r = E_UNSUPPORTED_OPERATION;
336 ret = sqlite3_key_func(pDb, pDbKey.get(), MAX_DATABASE_AES_KEY_LENGTH * 2);
339 if (ret != SQLITE_OK)
341 r = __ConvertNativeSqliteErrorToResult(ret);
342 SysLog(NID_IO, "[%s] sqlite3_key() failed (%d, %s).", GetErrorMessage(r), ret, sqlite3_errmsg(pDb));
357 _DatabaseImpl::Construct(const String& dbPath, const char* pOpenMode, const ByteBuffer* pSecretKey)
359 SysAssertf(__pDatabase == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class\n");
360 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(dbPath, _AppInfo::IsOspCompat()) == true,
361 E_INVALID_ARG, "The specified dbPath (%ls) is invalid.", dbPath.GetPointer());
362 SysTryReturnResult(NID_IO, !(pSecretKey && pSecretKey->GetRemaining() <= 0), E_INVALID_ARG,
363 "The specified secretKey is invalid.");
366 bool isValidOpenMode = _DatabaseImpl::VerifyDatabaseOpenMode(pOpenMode, legacyMode);
367 SysTryReturnResult(NID_IO, isValidOpenMode == true, E_INVALID_ARG, "The specified openMode is invalid. (%s)", pOpenMode);
372 bool isFilePathExist = false;
373 bool isParentDirPathExist = false;
375 String parentDirPath;
379 case DB_OPEN_READ_WRITE:
380 openFlags = SQLITE_OPEN_READWRITE;
382 case DB_OPEN_READ_ONLY:
383 openFlags = SQLITE_OPEN_READONLY;
385 case (DB_OPEN_READ_WRITE | DB_OPEN_CREATE):
386 openFlags = (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
389 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
390 return E_INVALID_ARG;
393 // extract directory path from a given Db file path
394 // Find index of last occurrence of character '/' in dbPath
395 result r = dbPath.LastIndexOf(L'/', dbPath.GetLength() - 1, lastIndex);
396 SysTryReturnResult(NID_IO, !IsFailed(r), E_INVALID_ARG,
397 "Missing directory path. SHOULD not happen.");
399 // extract directory path from dbPath starting from index 0 to lastIndex.
400 r = dbPath.SubString(0, lastIndex, parentDirPath);
401 SysTryReturnResult(NID_IO, !IsFailed(r), E_INVALID_ARG,
402 "Missing directory path. SHOULD not happen.");
404 // TODO: Test sqlite3_open_v3() without parent directory.
405 //check existence of parent directory
406 isParentDirPathExist = _FileImpl::IsFileExist(String(parentDirPath));
407 SysTryReturnResult(NID_IO, isParentDirPathExist == true, E_INVALID_ARG,
408 "Parent Directory dose not exist.");
410 unique_ptr<char[]> pDbPath(_StringConverter::CopyToCharArrayN(dbPath));
411 SysTryReturn(NID_IO, pDbPath, GetLastResult(), GetLastResult(), "[%s] pDbPath is null.", GetErrorMessage(GetLastResult()));
413 //check existence of file
414 isFilePathExist = _FileImpl::IsFileExist(dbPath);
415 if (isFilePathExist == true)
417 //check if it is a directory
418 SysTryReturnResult(NID_IO, !IsDirectory(dbPath), E_INVALID_ARG, "Given path is not a File.");
421 _DatabaseMode dbMode = DATABASE_MODE_NONE;
422 dbMode = _SecureIoUtil::GetDatabaseMode(pDbPath.get());
423 SysTryReturnResult(NID_IO, dbMode != DATABASE_MODE_ERROR, E_INVALID_FORMAT,
424 "GetDatabaseMode function failed.");
426 if (pSecretKey && _SecureIoUtil::IsNormalDatabase(dbMode))
428 SysTryReturnResult(NID_IO, false, E_INVALID_ARG,
429 "Trying to open a normal database in secure mode.");
431 else if (!pSecretKey && _SecureIoUtil::IsSecureDatabase(dbMode))
433 SysTryReturnResult(NID_IO, false, E_INVALID_ARG,
434 "Trying to open a secure database in normal mode.");
444 if (legacyMode == DB_OPEN_READ_WRITE || legacyMode == DB_OPEN_READ_ONLY)
446 SysLog(NID_IO, "[E_FILE_NOT_FOUND] File not found.");
447 r = E_FILE_NOT_FOUND;
452 // open/create the database
453 ret = sqlite3_open_v2(pDbPath.get(), &pDb, openFlags, null);
454 if (ret != SQLITE_OK)
456 if (!_AppInfo::IsOspCompat())
458 r = __ConvertNativeSqliteErrorToDetailResult(ret);
462 case E_OBJECT_LOCKED:
463 case E_INVALID_OPERATION:
471 r = __ConvertNativeSqliteErrorToResult(ret);
474 SysLog(NID_IO, "[%s] Failed to open database file (%s). (%d, %s).", GetErrorMessage(r), pDbPath.get(),
475 ret, sqlite3_errmsg(static_cast< sqlite3* >(pDb)));
481 unique_ptr<byte[]> pDbKey(_SecureIoUtil::GenerateDatabaseKeyN(pSecretKey));
482 SysTryReturnResult(NID_IO, pDbKey != null, E_IO, "GenerateDatabaseKeyN returned null.");
486 r = SystemInfo::GetValue(L"http://tizen.org/feature/database.encryption", secure);
487 SysTryReturnResult(NID_IO, !IsFailed(r), E_SYSTEM, "The method cannot proceed due to a severe system error.");
488 SysTryReturnResult(NID_IO, secure == true, E_UNSUPPORTED_OPERATION, "This operation is not supported.");
490 ret = sqlite3_key(pDb, pDbKey.get(), MAX_DATABASE_AES_KEY_LENGTH * 2);
492 int (* sqlite3_key_func)(sqlite3*, const void*, int) = null;
493 void* handle = dlopen(_DATABASE_LIBRARY_PATH, RTLD_LAZY | RTLD_LOCAL);
494 SysTryReturnResult(NID_IO, handle != null, E_SYSTEM,
495 "Failed to dlopen database library file (%s)", dlerror());
497 sqlite3_key_func = reinterpret_cast< int (*)(sqlite3*, const void*, int) >(dlsym(handle, _DATABASE_ENCRYPTION_SYMBOL));
498 if (sqlite3_key_func == null)
500 SysLog(NID_IO, "This operation is not supported. (%s)", dlerror());
502 r = E_UNSUPPORTED_OPERATION;
506 ret = sqlite3_key_func(pDb, pDbKey.get(), MAX_DATABASE_AES_KEY_LENGTH * 2);
509 if (ret != SQLITE_OK)
511 if (!_AppInfo::IsOspCompat())
520 SysLog(NID_IO, "[%s] Failed to create secret key (%d, %s).", GetErrorMessage(r), ret,
521 sqlite3_errmsg(static_cast< sqlite3* >(pDb)));
536 _DatabaseImpl::CreateStatementN(const String& statement)
538 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
541 char* pStrStmt = null;
542 sqlite3_stmt* pSqlStmt = null;
543 result r = E_SUCCESS;
545 unique_ptr<DbStatement> pDbStatement(_DbStatementImpl::CreateDbStatementInstanceN());
547 SysTryReturn(NID_IO, pDbStatement != null, null, E_OUT_OF_MEMORY,
548 "[E_OUT_OF_MEMORY] The memory is insufficient.");
550 unique_ptr<char[]> pUnTrimStatement(_StringConverter::CopyToCharArrayN(statement));
551 if (pUnTrimStatement == null)
557 // trim leading spaces
558 pStrStmt = pUnTrimStatement.get();
559 while ((*pStrStmt == ' ') || (*pStrStmt == '\t'))
564 // prepare the sql statement
565 ret = sqlite3_prepare_v2((sqlite3*) __pDatabase, pStrStmt, strlen(pStrStmt), &pSqlStmt, null);
566 if (ret != SQLITE_OK)
568 if (!_AppInfo::IsOspCompat())
570 r = __ConvertNativeSqliteErrorToDetailResult(ret);
573 case E_ILLEGAL_ACCESS:
575 case E_INVALID_FORMAT:
577 case E_INVALID_OPERATION:
585 r = __ConvertNativeSqliteErrorToResult(ret);
588 SysLog(NID_IO, "[%s] Failed to prepare SQL statement (%s). (%d, %s).", GetErrorMessage(r), pStrStmt,
589 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
593 // register the sql stmt in DbStatement
594 // accessing private variable of DbStatement.
595 _DbStatementImpl::GetInstance(*pDbStatement)->__pStmt = pSqlStmt;
596 _DbStatementImpl::GetInstance(*pDbStatement)->__pDatabase = __pDatabase;
598 if (strncasecmp(pStrStmt, "select", 6) == 0)
600 _DbStatementImpl::GetInstance(*pDbStatement)->__stmtType = DB_STATEMENT_TYPE_SELECT;
604 _DbStatementImpl::GetInstance(*pDbStatement)->__stmtType = DB_STATEMENT_TYPE_OTHER;
608 return pDbStatement.release();
616 _DatabaseImpl::ExecuteStatementN(const DbStatement& statement)
618 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
619 SysTryReturn(NID_IO, _DbStatementImpl::GetInstance(statement)->__pStmt != null, null, E_INVALID_ARG,
620 "[E_INVALID_ARG] Invalid DbStatement was passed.(null handle was assigned)");
623 DbEnumerator* pDbEnum = null;
624 result r = E_SUCCESS;
626 ret = sqlite3_reset((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
627 if (ret != SQLITE_OK)
629 if (!_AppInfo::IsOspCompat())
631 r = __ConvertNativeSqliteErrorToDetailResult(ret);
635 case E_ILLEGAL_ACCESS:
637 case E_INVALID_FORMAT:
639 case E_INVALID_OPERATION:
647 r = __ConvertNativeSqliteErrorToResult(ret);
650 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
651 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
656 ret = sqlite3_step((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
661 ret = sqlite3_reset((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
662 if (ret != SQLITE_OK)
664 if (!_AppInfo::IsOspCompat())
666 r = __ConvertNativeSqliteErrorToDetailResult(ret);
670 case E_ILLEGAL_ACCESS:
672 case E_INVALID_FORMAT:
674 case E_INVALID_OPERATION:
682 r = __ConvertNativeSqliteErrorToResult(ret);
685 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
686 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
692 if (_DbStatementImpl::GetInstance(statement)->__stmtType == DB_STATEMENT_TYPE_SELECT)
694 unique_ptr<DbEnumerator> pTempDbEnum(_DbEnumeratorImpl::CreateDbEnumeratorInstanceN());
696 SysTryReturn(NID_IO, pTempDbEnum != null, null, E_OUT_OF_MEMORY,
697 "[E_OUT_OF_MEMORY] The memory is insufficient.");
699 _DbEnumeratorImpl::GetInstance(*pTempDbEnum)->__pEnum = _DbStatementImpl::GetInstance(statement)->__pStmt;
700 _DbEnumeratorImpl::GetInstance(*pTempDbEnum)->__pDatabase = _DbStatementImpl::GetInstance(statement)->__pDatabase;
703 ret = sqlite3_reset((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
704 if (ret != SQLITE_OK)
706 if (!_AppInfo::IsOspCompat())
708 r = __ConvertNativeSqliteErrorToDetailResult(ret);
712 case E_ILLEGAL_ACCESS:
714 case E_INVALID_FORMAT:
716 case E_INVALID_OPERATION:
724 r = __ConvertNativeSqliteErrorToResult(ret);
727 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
728 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
733 pDbEnum = pTempDbEnum.release();
738 goto REDO_SQLITE_STEP;
743 if (!_AppInfo::IsOspCompat())
745 r = __ConvertNativeSqliteErrorToDetailResult(ret);
748 case E_ILLEGAL_ACCESS:
749 case E_INVALID_OPERATION:
757 r = __ConvertNativeSqliteErrorToResult(ret);
760 SysLog(NID_IO, "[%s] Failed to execute SQL statement. (%d, %s).", GetErrorMessage(r), ret,
761 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
765 SetLastResult(E_SUCCESS);
774 _DatabaseImpl::ExecuteSql(const String& sql, bool autoCommit)
776 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
779 char* pSqlStr = null;
780 result r = E_SUCCESS;
782 unique_ptr<char[]> pUnTrimStatement(_StringConverter::CopyToCharArrayN(sql));
783 if (pUnTrimStatement == null)
789 // trim leading spaces
790 pSqlStr = pUnTrimStatement.get();
791 while ((*pSqlStr == ' ') || (*pSqlStr == '\t'))
796 if (strncasecmp(pSqlStr, "select", 6) == 0)
798 r = E_INVALID_OPERATION;
802 ret = sqlite3_exec((sqlite3*) __pDatabase, pSqlStr, null, null, null);
803 if (ret != SQLITE_OK)
805 if (!_AppInfo::IsOspCompat())
807 r = __ConvertNativeSqliteErrorToDetailResult(ret);
810 case E_ILLEGAL_ACCESS:
811 case E_INVALID_OPERATION:
819 r = __ConvertNativeSqliteErrorToResult(ret);
822 SysLog(NID_IO, "[%s] Failed to execute SQL statement. (%d, %s).", GetErrorMessage(r), ret,
823 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
834 _DatabaseImpl::QueryN(const String& query)
836 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
840 sqlite3_stmt* pSqlStmt = null;
841 unique_ptr<DbEnumerator> pDbEnum(null);
842 result r = E_SUCCESS;
844 unique_ptr<char[]> pUnTrimStatement(_StringConverter::CopyToCharArrayN(query));
845 if (pUnTrimStatement == null)
851 // trim leading spaces
852 pQuery = pUnTrimStatement.get();
853 while ((*pQuery == ' ') || (*pQuery == '\t'))
858 if ((strncasecmp(pQuery, "select", 6) != 0) && (strncasecmp(pQuery, "PRAGMA", 6) != 0))
860 r = E_INVALID_OPERATION;
864 // prepare the sql statement
865 ret = sqlite3_prepare_v2((sqlite3*) __pDatabase, pQuery, strlen(pQuery), &pSqlStmt, null);
866 if (ret != SQLITE_OK)
868 if (!_AppInfo::IsOspCompat())
870 r = __ConvertNativeSqliteErrorToDetailResult(ret);
873 case E_ILLEGAL_ACCESS:
875 case E_INVALID_FORMAT:
877 case E_INVALID_OPERATION:
885 r = __ConvertNativeSqliteErrorToResult(ret);
888 SysLog(NID_IO, "[%s] Failed to prepare SQL statement (%s). (%d, %s).", GetErrorMessage(r), pQuery,
889 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
893 // ret = sqlite3_reset((sqlite3_stmt *) pSqlStmt);
894 // if (ret != SQLITE_OK)
896 // r = __ConvertNativeSqliteErrorToResult(ret);
897 // SysLog(NID_IO, "[_DatabaseImpl] ERROR: [%s] Failed to reset SQL statement.", GetErrorMessage(r));
901 ret = sqlite3_step(pSqlStmt);
909 pDbEnum.reset(_DbEnumeratorImpl::CreateDbEnumeratorInstanceN());
911 SysTryCatch(NID_IO, pDbEnum != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
912 "[E_OUT_OF_MEMORY] The memory is insufficient.");
914 _DbEnumeratorImpl::GetInstance(*pDbEnum)->__pEnum = pSqlStmt;
915 _DbEnumeratorImpl::GetInstance(*pDbEnum)->__pDatabase = __pDatabase;
916 _DbEnumeratorImpl::GetInstance(*pDbEnum)->__shouldReleaseResource = true;
918 // doing a reset again, so that enumerator first MoveNext() give the first row.
919 ret = sqlite3_reset((sqlite3_stmt*) pSqlStmt);
920 if (ret != SQLITE_OK)
922 if (!_AppInfo::IsOspCompat())
924 r = __ConvertNativeSqliteErrorToDetailResult(ret);
928 case E_ILLEGAL_ACCESS:
930 case E_INVALID_FORMAT:
932 case E_INVALID_OPERATION:
940 r = __ConvertNativeSqliteErrorToResult(ret);
943 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
944 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
950 if (!_AppInfo::IsOspCompat())
952 r = __ConvertNativeSqliteErrorToDetailResult(ret);
955 case E_ILLEGAL_ACCESS:
957 case E_INVALID_OPERATION:
965 r = __ConvertNativeSqliteErrorToResult(ret);
968 SysLog(NID_IO, "[%s] Failed to exectue SQL statement (%s). (%d, %s).", GetErrorMessage(r), pQuery,
969 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
974 return pDbEnum.release();
977 sqlite3_finalize(pSqlStmt);
983 _DatabaseImpl::BeginTransaction(void)
985 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
986 SysTryReturnResult(NID_IO, __transactionGoingOn == false, E_INVALID_STATE,
987 "A transaction is already in progress.");
989 result r = E_SUCCESS;
991 if (sqlite3_get_autocommit((sqlite3*) __pDatabase) == 0)
993 SysLog(NID_IO, "[E_INVALID_STATE] Already in transaction mode.");
994 return E_INVALID_STATE;
997 int ret = sqlite3_exec((sqlite3*) __pDatabase, "BEGIN", null, null, null);
998 if (ret != SQLITE_OK)
1000 if (!_AppInfo::IsOspCompat())
1002 r = __ConvertNativeSqliteErrorToDetailResult(ret);
1006 case E_ILLEGAL_ACCESS:
1007 case E_OBJECT_LOCKED:
1009 case E_INVALID_FORMAT:
1010 case E_STORAGE_FULL:
1011 case E_INVALID_OPERATION:
1018 r = __ConvertNativeSqliteErrorToResult(ret);
1021 SysLog(NID_IO, "[%s] Failed to begin transaction. (%d, %s)", GetErrorMessage(r), ret,
1022 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
1026 __transactionGoingOn = true;
1033 _DatabaseImpl::CommitTransaction(void)
1035 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1036 SysTryReturnResult(NID_IO, __transactionGoingOn == true, E_INVALID_STATE,
1037 "A transaction is already in progress.");
1040 result r = E_SUCCESS;
1042 if (sqlite3_get_autocommit((sqlite3*) __pDatabase) != 0)
1044 SysLog(NID_IO, "[E_INVALID_STATE] ERROR Message: Not in transaction mode.");
1045 return E_INVALID_STATE;
1048 ret = sqlite3_exec((sqlite3*) __pDatabase, "COMMIT", null, null, null);
1049 if (ret != SQLITE_OK)
1051 if (!_AppInfo::IsOspCompat())
1053 r = __ConvertNativeSqliteErrorToDetailResult(ret);
1057 case E_ILLEGAL_ACCESS:
1058 case E_INVALID_OPERATION:
1065 r = __ConvertNativeSqliteErrorToResult(ret);
1068 SysLog(NID_IO, "[%s] Failed to commit transaction. (%d, %s)", GetErrorMessage(r), ret,
1069 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
1073 __transactionGoingOn = false;
1080 _DatabaseImpl::RollbackTransaction(void)
1082 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1083 SysTryReturnResult(NID_IO, __transactionGoingOn == true, E_INVALID_STATE,
1084 "No transaction in progress.");
1087 result r = E_SUCCESS;
1089 if (sqlite3_get_autocommit((sqlite3*) __pDatabase) != 0)
1091 SysLog(NID_IO, "[E_SUCCESS] No transaction in progress.");
1092 //return E_INVALID_STATE;
1096 ret = sqlite3_exec((sqlite3*) __pDatabase, "ROLLBACK", null, null, null);
1097 if (ret != SQLITE_OK)
1099 if (!_AppInfo::IsOspCompat())
1101 r = __ConvertNativeSqliteErrorToDetailResult(ret);
1105 case E_ILLEGAL_ACCESS:
1106 case E_INVALID_OPERATION:
1113 r = __ConvertNativeSqliteErrorToResult(ret);
1116 SysLog(NID_IO, "[%s] Failed to rollback the transaction. (%d, %s)", GetErrorMessage(r), ret,
1117 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
1121 __transactionGoingOn = false;
1128 _DatabaseImpl::GetName(void) const
1130 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1132 SetLastResult(E_SUCCESS);
1137 _DatabaseImpl::RegisterUserFunction(const String& functionName, const int argumentCount, void* pUserData,
1138 _IDbUserFunctionListener* pUserFunctionListener,
1139 _IDbUserAggregateListener* pUserAggregateListener)
1141 result r = E_SUCCESS;
1142 int sqliteEncoding = 0;
1145 unique_ptr<_DbContextImpl> pDbContext(null);
1146 _DbContextImpl* pTempDbContext = null;
1147 bool entryFound = false;
1150 // Validate input parameters
1151 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1152 SysTryReturnResult(NID_IO, functionName.GetLength() > 0, E_INVALID_ARG,
1153 "Invalid funcName length.");
1154 SysTryReturnResult(NID_IO, argumentCount >= 0 && argumentCount <= MAX_FUNCTION_ARGUMENT_COUNT, E_INVALID_ARG,
1155 "argumentCount < 0 or > 127.");
1157 if (pUserFunctionListener != null && pUserAggregateListener != null)
1159 SysTryReturnResult(NID_IO, 0, E_INVALID_ARG,
1160 "FunctionListener and AggregateListener cannot be registered together");
1163 //select the equivalent sqlite encoding.
1165 unique_ptr<ByteBuffer> pFuncNameBuf(StringUtil::StringToUtf8N(functionName));
1166 SysTryReturn(NID_IO, pFuncNameBuf != null, GetLastResult(),
1167 GetLastResult(), "[%s] Invalid Function name.", GetErrorMessage(GetLastResult()));
1169 utf8len = pFuncNameBuf->GetLimit();
1170 SysTryReturnResult(NID_IO, utf8len > 0 && utf8len <= MAX_UTF8_BYTES, E_INVALID_ARG,
1171 "functionName length in utf8 bytes should be >0 && <=255.");
1173 sqliteEncoding = SQLITE_UTF8; // support only UTF8
1175 //check if the (FunctionName, argumentCount) already exist in the list
1176 for (i = 0; i < __userFunctionContextList.GetCount(); i++)
1178 pTempDbContext = dynamic_cast<_DbContextImpl*> (__userFunctionContextList.GetAt(i));
1179 SysTryReturnResult(NID_IO, pTempDbContext, E_IO, "The __userFunctionContextList has an invalid element.");
1180 if ((pTempDbContext->__argumentCount == argumentCount) &&
1181 (pTempDbContext->__functionName == functionName))
1188 if (entryFound && (null != pUserFunctionListener || null != pUserAggregateListener))
1190 SysTryReturnResult(NID_IO, 0, E_INVALID_ARG,
1191 "(functionName, argumentCount) already registered");
1194 if (pUserFunctionListener != null) // register FunctionListener
1196 pDbContext.reset(new (std::nothrow) _DbContextImpl());
1197 SysTryReturnResult(NID_IO, pDbContext != null, E_OUT_OF_MEMORY,
1198 "The memory is insufficient.");
1200 ret = sqlite3_create_function((sqlite3*) __pDatabase,
1201 (const char*) pFuncNameBuf->GetPointer(), argumentCount, sqliteEncoding, pDbContext.get(),
1202 _DatabaseImpl::UserFunctionListener, null, null);
1204 else if (pUserAggregateListener != null) // register both FunctionStepListener and FunctionFinalListener
1206 pDbContext.reset(new (std::nothrow) _DbContextImpl());
1208 SysTryReturnResult(NID_IO, pDbContext != null, E_OUT_OF_MEMORY,
1209 "The memory is insufficient.");
1211 ret = sqlite3_create_function((sqlite3*) __pDatabase,
1212 (const char*) pFuncNameBuf->GetPointer(), argumentCount, sqliteEncoding, pDbContext.get(),
1213 null, _DatabaseImpl::UserFunctionStepListener, _DatabaseImpl::UserFunctionFinalListener);
1215 else // Delete registered user function/Aggregate
1217 ret = sqlite3_create_function((sqlite3*) __pDatabase,
1218 (const char*) pFuncNameBuf->GetPointer(), argumentCount, sqliteEncoding, null, null, null, null);
1221 if (ret != SQLITE_OK) //error
1223 r = __ConvertNativeSqliteErrorToResult(ret);
1224 SysLog(NID_IO, "[%s] ERROR Message: [%s], Failed to create/delete user defined SQL function.", GetErrorMessage(r),
1225 sqlite3_errmsg((sqlite3*)__pDatabase));
1229 if (entryFound && (!pUserFunctionListener && !pUserAggregateListener)) // delete the user function entry from list
1231 r = __userFunctionContextList.Remove(*pTempDbContext, true);
1232 SysTryReturn(NID_IO, !IsFailed(r), GetLastResult(),
1233 GetLastResult(), "[%s] Failed to remove user function context to the list.", GetErrorMessage(GetLastResult()));
1236 if (pDbContext != null)
1238 //store listener and user data
1239 pDbContext->__pUserData = pUserData;
1240 pDbContext->__argumentCount = argumentCount;
1241 pDbContext->__functionName = functionName;
1242 if (pUserFunctionListener != null)
1244 pDbContext->__pUserFunctionListener = pUserFunctionListener;
1246 if (pUserAggregateListener != null)
1248 pDbContext->__pUserAggregateListener = pUserAggregateListener;
1251 // add entry to the list
1252 r = __userFunctionContextList.Add(*(pDbContext.release()));
1253 SysTryReturn(NID_IO, !IsFailed(r), GetLastResult(),
1254 GetLastResult(), "[%s] Failed to add user function context to the list.", GetErrorMessage(GetLastResult()));
1261 _DatabaseImpl::RegisterUserCollation(const String& collationName, void* pUserData,
1262 _IDbUserCollationListener* pUserCollationListener)
1264 result r = E_SUCCESS;
1265 int sqliteEncoding = 0;
1268 unique_ptr<_DbContextImpl> pDbContext(null);
1269 _DbContextImpl* pTempDbContext = null;
1270 bool entryFound = false;
1273 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1274 SysTryReturnResult(NID_IO, collationName.GetLength() > 0, E_INVALID_ARG,
1275 "Invalid collationName length.");
1277 sqliteEncoding = SQLITE_UTF8; // support only UTF8
1279 unique_ptr<ByteBuffer> pColNameBuf(StringUtil::StringToUtf8N(collationName));
1280 SysTryReturn(NID_IO, pColNameBuf != null, GetLastResult(), GetLastResult(), "[%s] Invalid Function name.",
1281 GetErrorMessage(GetLastResult()));
1283 utf8len = pColNameBuf->GetLimit(); // get UTF_8 bytes length
1284 SysTryReturnResult(NID_IO, utf8len > 0 && utf8len <= MAX_UTF8_BYTES, E_INVALID_ARG,
1285 "functionName length in utf8 bytes should be >0 && <=255.");
1287 //check if the (FunctionName) already registered
1288 for (i = 0; i < __userCollationContextList.GetCount(); i++)
1290 pTempDbContext = dynamic_cast< _DbContextImpl* >(__userCollationContextList.GetAt(i));
1291 SysTryReturnResult(NID_IO, pTempDbContext, E_IO, "The __userCollationContextList has an invalid element.");
1292 if (pTempDbContext->__collationName == collationName)
1299 if (entryFound && (pUserCollationListener != null)) // check if the operation is to delete the user function
1301 SysTryReturnResult(NID_IO, 0, E_INVALID_ARG, "(collationName) already registered");
1304 if (pUserCollationListener != null)
1306 pDbContext.reset(new (std::nothrow) _DbContextImpl());
1307 SysTryReturnResult(NID_IO, pDbContext != null, E_OUT_OF_MEMORY,
1308 "The memory is insufficient.");
1310 // register CollationListener()
1311 ret = sqlite3_create_collation((sqlite3*) __pDatabase, (const char*) pColNameBuf->GetPointer(), sqliteEncoding, pDbContext.get(),
1312 _DatabaseImpl::UserCollationListener);
1314 else // delete Collating function
1316 ret = sqlite3_create_collation((sqlite3*) __pDatabase, (const char*) pColNameBuf->GetPointer(), sqliteEncoding, null, null);
1319 if (ret != SQLITE_OK)
1321 r = __ConvertNativeSqliteErrorToResult(ret);
1322 SysLog(NID_IO, "[%s] ERROR Message: [%s], Failed to create/delete user defined SQL Collation.", GetErrorMessage(r),
1323 sqlite3_errmsg((sqlite3*)__pDatabase));
1327 if (entryFound && !pUserCollationListener) // delete the user collation entry from list
1329 r = __userCollationContextList.Remove(*pTempDbContext, true);
1330 SysTryReturn(NID_IO, !IsFailed(r), GetLastResult(),
1331 GetLastResult(), "[%s] Failed to remove user collation context from the list.", GetErrorMessage(GetLastResult()));
1334 if (pDbContext != null)
1336 //store listener and user data
1337 pDbContext->__pUserData = pUserData;
1338 pDbContext->__collationName = collationName;
1339 pDbContext->__pUserCollationListener = pUserCollationListener;
1340 // add entry to the list
1341 r = __userCollationContextList.Add((*(pDbContext.release())));
1342 SysTryReturn(NID_IO, !IsFailed(r), GetLastResult(),
1343 GetLastResult(), "[%s] Failed to add user collation context to the list.", GetErrorMessage(GetLastResult()));
1351 _DatabaseImpl::GetLastInsertRowId(void) const
1353 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1355 // Retrieve last inserted row Id of the specified Db connection.
1356 // sqlite rowIds starts from 1 to max. 0 means no rows available in the database.
1357 // even if we delete the last inserted row, it still returns the rowid of last insert.
1358 // and does not care about any deletions happened.
1359 long long insertRowId = sqlite3_last_insert_rowid(static_cast< sqlite3* >(__pDatabase));
1360 if (insertRowId == 0)
1371 _DatabaseImpl::Delete(const String& databasePath)
1373 result r = E_SUCCESS;
1376 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(databasePath, _AppInfo::IsOspCompat()) == true,
1377 E_INVALID_ARG, " [%ls] is not compatible.", databasePath.GetPointer());
1379 unique_ptr<char[]> pDbPath(_StringConverter::CopyToCharArrayN(databasePath));
1380 if (pDbPath == null)
1382 return GetLastResult();
1386 ret = unlink(pDbPath.get());
1389 r = __ConvertNativeErrorToResult(errno);
1396 _DatabaseImpl::Exists(const String& databasePath)
1398 return _FileImpl::IsFileExist(databasePath);
1402 _DatabaseImpl::UserFunctionListener(sqlite3_context* pContext, int argumentCount, sqlite3_value** pArgList)
1404 _DbContextImpl* pDbContext = null;
1406 pDbContext = static_cast< _DbContextImpl* >(sqlite3_user_data(pContext));
1408 SysTryReturnVoidResult(NID_IO, pDbContext, E_INVALID_STATE, "[E_INVALID_STATE] pDbContext is null.");
1409 SysTryReturnVoidResult(NID_IO, pDbContext->__pUserFunctionListener, E_INVALID_STATE,
1410 "[E_INVALID_STATE] UserAggregateListener is null.");
1412 //Set DbContext data
1413 if (pDbContext->__pContext != (void*) pContext)
1415 pDbContext->__pContext = (void*) pContext;
1418 if (pDbContext->__argumentCount != argumentCount)
1420 SysLog(NID_IO, "Message: __argumentCount mismatch.");
1421 pDbContext->__argumentCount = argumentCount;
1424 if (pDbContext->__pArgList != (void**) pArgList)
1426 pDbContext->__pArgList = (void**) pArgList;
1428 // Invoke the user listener method
1429 pDbContext->__pUserFunctionListener->OnDbUserFunction(*pDbContext, argumentCount);
1431 SetLastResult(E_SUCCESS);
1435 _DatabaseImpl::UserFunctionStepListener(sqlite3_context* pContext, int argumentCount, sqlite3_value** pArgList)
1437 _DbContextImpl* pDbContext = null;
1439 pDbContext = static_cast< _DbContextImpl* >(sqlite3_user_data(pContext));
1441 SysTryReturnVoidResult(NID_IO, pDbContext, E_INVALID_STATE, "[E_INVALID_STATE] pDbContext is null.");
1442 SysTryReturnVoidResult(NID_IO, pDbContext->__pUserAggregateListener, E_INVALID_STATE,
1443 "[E_INVALID_STATE] __pDbContextImpl->__pUserAggregateListener is null.");
1445 //Set DbContext data
1446 if (pDbContext->__pContext != (void*) pContext)
1448 pDbContext->__pContext = (void*) pContext;
1451 if (pDbContext->__argumentCount != argumentCount)
1453 pDbContext->__argumentCount = argumentCount;
1456 if (pDbContext->__pArgList != (void**) pArgList)
1458 pDbContext->__pArgList = (void**) pArgList;
1461 // invoke the user listener method
1462 pDbContext->__pUserAggregateListener->OnDbUserAggregateStep(*pDbContext, argumentCount);
1464 SetLastResult(E_SUCCESS);
1468 _DatabaseImpl::UserFunctionFinalListener(sqlite3_context* pContext)
1470 _DbContextImpl* pDbContext = null;
1472 pDbContext = static_cast< _DbContextImpl* >(sqlite3_user_data(pContext));
1474 SysTryReturnVoidResult(NID_IO, pDbContext, E_INVALID_STATE, "[E_INVALID_STATE] pDbContext is null.");
1475 SysTryReturnVoidResult(NID_IO, pDbContext->__pUserAggregateListener, E_INVALID_STATE,
1476 "[E_INVALID_STATE] UserAggregateListener is null.");
1478 // set context and user data
1479 if (pDbContext->__pContext != (void*) pContext)
1481 pDbContext->__pContext = (void*) pContext;
1484 // invoke the user listener method
1485 pDbContext->__pUserAggregateListener->OnDbUserAggregateFinal(*pDbContext);
1487 SetLastResult(E_SUCCESS);
1491 _DatabaseImpl::UserCollationListener(void* pUserData, int length1, const void* pInput1, int length2, const void* pInput2)
1493 _DbContextImpl* pDbContext = null;
1494 char* pDataInput = null;
1498 pDbContext = static_cast< _DbContextImpl* >(pUserData);
1500 SysTryReturn(NID_IO, pDbContext, 0, E_INVALID_STATE, "[E_INVALID_STATE] pDbContext is null.");
1501 SysTryReturn(NID_IO, pDbContext->__pUserCollationListener, 0, E_INVALID_STATE,
1502 "[E_INVALID_STATE] UserCollationListener is null.");
1504 if (length1 > 0 && (const char*) pInput1 != null)
1506 pDataInput = (char*) malloc((length1 + 1) * sizeof(char));
1508 if (pDataInput == null)
1513 memset(pDataInput, 0, length1 + 1);
1514 strncpy(pDataInput, (const char*) pInput1, length1);
1516 string1.Append((const char*) pDataInput);
1520 if (length2 > 0 && (const char*) pInput2 != null)
1522 pDataInput = (char*) malloc((length2 + 1) * sizeof(char));
1524 if (pDataInput == null)
1529 memset(pDataInput, 0, length2 + 1);
1530 strncpy(pDataInput, (const char*) pInput2, length2);
1532 string2.Append((const char*) pDataInput);
1536 SetLastResult(E_SUCCESS);
1538 return pDbContext->__pUserCollationListener->OnDbUserCollation(string1, string2, pUserData);
1542 _DatabaseImpl::ConvertToSecureDatabase(const String& plainDbPath, const String& secureDbPath, const ByteBuffer* pKey)
1544 result r = E_SUCCESS;
1546 String parentDirPath;
1547 FileAttributes attr;
1549 if (Database::Exists(secureDbPath))
1551 if (GetLastResult() == E_SUCCESS)
1553 r = File::GetAttributes(secureDbPath, attr);
1556 if (attr.IsDirectory())
1558 return E_INVALID_ARG;
1562 return E_FILE_ALREADY_EXIST;
1576 unique_ptr<Database>pDatabase(new (std::nothrow) Database());
1577 SysTryReturnResult(NID_IO, pDatabase, E_OUT_OF_MEMORY, "The memory is insufficient.");
1579 r = pDatabase->Construct(secureDbPath, "a+");
1580 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1582 pDatabase.reset(new (std::nothrow) Database());
1583 SysTryReturnResult(NID_IO, pDatabase, E_OUT_OF_MEMORY, "The memory is insufficient.");
1585 r = pDatabase->Construct(plainDbPath, "r+");
1586 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1588 unique_ptr<String> pSqlStr(new (std::nothrow) String(MAX_DATABASE_SQL_LENGTH));
1589 SysTryReturnResult(NID_IO, pSqlStr != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1591 unique_ptr<char[]> pPhysicalDbPath(_StringConverter::CopyToCharArrayN(secureDbPath));
1592 SysTryReturn(NID_IO, pPhysicalDbPath != null, GetLastResult(), GetLastResult(), "[%s] Invalid file path.", GetErrorMessage(GetLastResult()));
1594 unique_ptr<byte[]> pDbKey(_SecureIoUtil::GenerateDatabaseKeyN(pKey));
1595 SysTryReturnResult(NID_IO, pDbKey != null, E_INVALID_ARG, "GenerateDatabaseKeyN returned null.");
1597 pSqlStr->Format(MAX_DATABASE_SQL_LENGTH, L"ATTACH DATABASE '%s' AS encrypted KEY '%s'", pPhysicalDbPath.get(), pDbKey.get());
1599 sql.Append(*pSqlStr);
1600 r = pDatabase->ExecuteSql(sql, true);
1601 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1604 unique_ptr<DbEnumerator> pEnum(pDatabase->QueryN(L"SELECT sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type!='meta' ORDER BY tbl_name, type DESC, name"));
1605 r = GetLastResult();
1611 String tempQuery(L"encrypted.");
1613 while (pEnum->MoveNext() == E_SUCCESS)
1615 r = pEnum->GetStringAt(0, schema);
1618 if (r == E_INVALID_STATE || r == E_TYPE_MISMATCH || r == E_INVALID_ENCODING_RANGE) //internal exception by this method
1625 if (schema.StartsWith(L"sqlite_", MAX_SQLCIPHER_SCHEMA_PREFIX_SIZE))
1630 r = schema.Insert(tempQuery, MAX_SQLCIPHER_SCHEMA_PREFIX_SIZE);
1636 r = pDatabase->ExecuteSql(schema, true);
1637 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to caller...", GetErrorMessage(r));
1643 SysPropagate(NID_IO, r);
1647 pEnum.reset(pDatabase->QueryN(L"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"));
1648 r = GetLastResult();
1654 while (pEnum->MoveNext() == E_SUCCESS)
1656 r = pEnum->GetStringAt(0, tableName);
1659 if (r == E_INVALID_STATE || r == E_TYPE_MISMATCH || r == E_INVALID_ENCODING_RANGE) //internal exception by this method
1667 if (tableName.StartsWith(L"sqlite_", 0))
1672 pSqlStr.reset(new (std::nothrow) String(MAX_DATABASE_SQL_LENGTH));
1673 SysTryReturnResult(NID_IO, pSqlStr, E_OUT_OF_MEMORY, "The memory is insufficient.");
1675 pSqlStr->Format(MAX_DATABASE_SQL_LENGTH, L"INSERT INTO encrypted.%ls SELECT * FROM %ls", tableName.GetPointer(), tableName.GetPointer());
1677 sql.Append(*pSqlStr);
1678 r = pDatabase->ExecuteSql(sql, true);
1679 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1686 SysPropagate(NID_IO, r);
1690 sql.Append(L"DETACH DATABASE encrypted");
1692 r = pDatabase->ExecuteSql(sql, true);
1693 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1699 _DatabaseImpl::GetInstance(Database& database)
1701 return database.__pDatabaseImpl;
1704 const _DatabaseImpl*
1705 _DatabaseImpl::GetInstance(const Database& database)
1707 return database.__pDatabaseImpl;