2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
19 * @file FIo_DatabaseImpl.cpp
20 * @brief This is the implementation file for _DatabaseImpl class.
26 #include <semaphore.h>
31 #include <unique_ptr.h>
35 #include <FBaseResult.h>
36 #include <FBaseSysLog.h>
38 #include <FIoDirectory.h>
39 #include <FIoDbTypes.h>
40 #include <FIoDatabase.h>
41 #include <FIoDbStatement.h>
42 #include <FIoDbEnumerator.h>
43 #include <FSysSystemInfo.h>
45 #include <FBase_StringConverter.h>
46 #include <FBaseUtilStringUtil.h>
47 #include <FBase_NativeError.h>
48 #include <FApp_AppInfo.h>
49 #include <FIo_FileImpl.h>
50 #include <FIo_DatabaseImpl.h>
51 #include <FIo_DbStatementImpl.h>
52 #include <FIo_DbEnumeratorImpl.h>
53 #include <FIo_DbContextImpl.h>
54 #include <FIo_SecureIoUtil.h>
55 #include <FIo_IDbUserListener.h>
58 using namespace Tizen::Base;
59 using namespace Tizen::App;
60 using namespace Tizen::Base::Runtime;
61 using namespace Tizen::Base::Utility;
62 using namespace Tizen::System;
64 namespace Tizen { namespace Io
67 // maximum argument count that can be passed to register user defined functions
68 const int MAX_FUNCTION_ARGUMENT_COUNT = 127;
69 const int MAX_UTF8_BYTES = 255; // maximum length of UTF8 bytes
70 const int MAX_MUTEX_NAME_LENGTH = 32; // maximum length of mutex name
71 const int MAX_DATABASE_AES_KEY_LENGTH = 16; //default key size for AES 128
72 const int MAX_DATABASE_SQL_LENGTH = 4096; //buffer length required to make sql query
73 const int MAX_SQLCIPHER_SCHEMA_PREFIX_SIZE = 13;//size of sqlCipher_ schema prefix name.
75 static const size_t _MAX_DB_OPENMODE_LENGTH = 2;
76 static const char _DATABASE_LIBRARY_PATH[] = "/usr/lib/libsqlite3.so.0";
77 static const char _DATABASE_ENCRYPTION_SYMBOL[] = "sqlite3_key";
79 _DatabaseImpl::_DatabaseImpl(void)
81 , __transactionGoingOn(false)
85 _DatabaseImpl::~_DatabaseImpl(void)
88 sqlite3_stmt* pSqlStmt = null;
92 pSqlStmt = sqlite3_next_stmt((sqlite3*) __pDatabase, 0);
93 while (pSqlStmt != null)
95 sqlite3_finalize(pSqlStmt);
96 pSqlStmt = sqlite3_next_stmt((sqlite3*) __pDatabase, 0);
99 int ret = sqlite3_close((sqlite3*) __pDatabase);
100 if (ret != SQLITE_OK)
102 r = __ConvertNativeSqliteErrorToResult(ret);
103 SysLog(NID_IO, "[%s] ERROR Message: [%s], Failed to close database.", GetErrorMessage(r),
104 sqlite3_errmsg((sqlite3*) __pDatabase));
109 __transactionGoingOn = false;
113 // release user context info
114 __userFunctionContextList.RemoveAll(true);
115 __userCollationContextList.RemoveAll(true);
120 _DatabaseImpl::IsDirectory(const String& databasePath)
123 result r = E_SUCCESS;
125 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(databasePath, _AppInfo::IsOspCompat()) == true,
126 E_INVALID_ARG, " [%ls] is not compatible.", databasePath.GetPointer());
128 r = _FileImpl::GetAttributes(databasePath, attr);
135 SetLastResult(E_SUCCESS);
136 return attr.IsDirectory();
140 _DatabaseImpl::VerifyDatabaseOpenMode(const char* pOpenMode, long& legacyMode)
142 if (pOpenMode == null)
144 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode is null.");
148 if (strlen(pOpenMode) > _MAX_DB_OPENMODE_LENGTH)
150 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
154 if (pOpenMode[0] == 'r')
156 if (pOpenMode[1] == '\0')
158 legacyMode = DB_OPEN_READ_ONLY;
160 else if (pOpenMode[1] == '+')
162 if (pOpenMode[2] == '\0')
164 legacyMode = DB_OPEN_READ_WRITE;
168 else if (pOpenMode[0] == 'a' && pOpenMode[1] == '+' && pOpenMode[2] == '\0')
170 legacyMode = (DB_OPEN_CREATE | DB_OPEN_READ_WRITE);
174 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
182 _DatabaseImpl::Construct(const String& dbPath, bool createIfNotExist)
184 long openMode = DB_OPEN_READ_WRITE;
186 if (!_FileImpl::IsFileExist(dbPath))
188 SysTryReturn(NID_IO, createIfNotExist == true, E_FILE_NOT_FOUND, E_FILE_NOT_FOUND,
189 "[E_FILE_NOT_FOUND] Database file does not exist. Create it first.");
190 openMode = DB_OPEN_READ_WRITE | DB_OPEN_CREATE;
193 return Construct(dbPath, openMode, null);
197 _DatabaseImpl::Construct(const String& dbPath, long openMode, const ByteBuffer* pSecretKey)
199 SysAssertf(__pDatabase == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class\n");
200 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(dbPath, _AppInfo::IsOspCompat()) == true,
201 E_INVALID_ARG, " [%ls] is not compatible.", dbPath.GetPointer());
202 SysTryReturnResult(NID_IO, !(pSecretKey && pSecretKey->GetRemaining() <= 0), E_INVALID_ARG,
203 "The specified secretKey is invalid.");
205 result r = E_SUCCESS;
209 bool isFilePathExist = false;
210 bool isParentDirPathExist = false;
212 String parentDirPath;
216 case (DB_OPEN_READ_WRITE):
217 openFlags = SQLITE_OPEN_READWRITE;
220 case (DB_OPEN_READ_ONLY):
221 openFlags = SQLITE_OPEN_READONLY;
224 case (DB_OPEN_READ_WRITE | DB_OPEN_CREATE):
225 openFlags = (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
229 SysLog(NID_IO, "[E_INVALID_ARG] The specified open mode flags are invalid.");
230 return E_INVALID_ARG;
233 // extract directory path from a given Db file path
234 // Find index of last occurrence of character '/' in dbPath
235 r = dbPath.LastIndexOf(L'/', dbPath.GetLength() - 1, lastIndex);
236 SysTryReturnResult(NID_IO, !IsFailed(r),
237 E_INVALID_ARG, "Missing directory path. SHOULD not happen.");
239 // extract directory path from dbPath starting from index 0 to lastIndex.
240 r = dbPath.SubString(0, lastIndex, parentDirPath);
241 SysTryReturnResult(NID_IO, !IsFailed(r),
242 E_INVALID_ARG, "Missing directory path. SHOULD not happen.");
244 // TODO: Test sqlite3_open_v3() without parent directory.
245 //check existence of parent directory
246 isParentDirPathExist = _FileImpl::IsFileExist(String(parentDirPath));
247 SysTryReturnResult(NID_IO, isParentDirPathExist == true, E_INVALID_ARG,
248 "Parent Directory does not exist.");
250 unique_ptr<char[]> pDbPath(_StringConverter::CopyToCharArrayN(dbPath));
252 SysTryCatch(NID_IO, pDbPath, , r, "[%s] pDbPath is null.", GetErrorMessage(r));
254 // check existence of file
255 isFilePathExist = _FileImpl::IsFileExist(dbPath);
256 if (isFilePathExist == true)
258 if (openMode == (DB_OPEN_READ_WRITE | DB_OPEN_CREATE))
260 SysLog(NID_IO, "[E_FILE_ALREADY_EXIST] File already exists.");
261 r = E_FILE_ALREADY_EXIST;
265 //check if it is a directory
266 if (IsDirectory(dbPath))
268 SysLog(NID_IO, "[E_DATABASE] Given path is not a File.");
274 _DatabaseMode dbMode = DATABASE_MODE_NONE;
275 dbMode = _SecureIoUtil::GetDatabaseMode(pDbPath.get());
276 SysTryCatch(NID_IO, dbMode != DATABASE_MODE_ERROR, r = E_IO, E_IO, "[E_IO] GetDatabaseMode function failed.");
278 if (pSecretKey && _SecureIoUtil::IsNormalDatabase(dbMode))
280 SysTryCatch(NID_IO, false, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Trying to open a normal database in secure mode.");
282 else if (!pSecretKey && _SecureIoUtil::IsSecureDatabase(dbMode))
284 SysTryCatch(NID_IO, false, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Trying to open a secure database in normal mode.");
294 if (openMode == DB_OPEN_READ_WRITE || openMode == DB_OPEN_READ_ONLY)
296 SysLog(NID_IO, "[E_FILE_NOT_FOUND] File not found when opened in DB_OPEN_READ_WRITE/DB_OPEN_READ_ONLY mode.");
297 r = E_FILE_NOT_FOUND;
302 // open/create the database
303 ret = sqlite3_open_v2(pDbPath.get(), &pDb, openFlags, null);
304 if (ret != SQLITE_OK)
306 r = __ConvertNativeSqliteErrorToResult(ret);
307 SysLog(NID_IO, "[%s] sqlite3_open_v2() failed (%d, %s).", GetErrorMessage(r), ret, sqlite3_errmsg(pDb));
313 unique_ptr<byte[]> pDbKey(_SecureIoUtil::GenerateDatabaseKeyN(pSecretKey));
314 SysTryReturnResult(NID_IO, pDbKey != null, E_IO, "GenerateDatabaseKeyN returned null.");
318 r = SystemInfo::GetValue(L"http://tizen.org/feature/database.encryption", secure);
319 SysTryReturnResult(NID_IO, !IsFailed(r), E_SYSTEM, "The method cannot proceed due to a severe system error.");
320 SysTryReturnResult(NID_IO, secure == true, E_UNSUPPORTED_OPERATION, "This operation is not supported.");
322 ret = sqlite3_key(pDb, pDbKey.get(), MAX_DATABASE_AES_KEY_LENGTH * 2);
324 int (* sqlite3_key_func)(sqlite3*, const void*, int) = null;
325 void* handle = dlopen(_DATABASE_LIBRARY_PATH, RTLD_LAZY | RTLD_LOCAL);
326 SysTryReturnResult(NID_IO, handle != null, E_SYSTEM,
327 "Failed to dlopen database library file (%s)", dlerror());
329 sqlite3_key_func = reinterpret_cast< int (*)(sqlite3*, const void*, int) >(dlsym(handle, _DATABASE_ENCRYPTION_SYMBOL));
330 if (sqlite3_key_func == null)
332 SysLog(NID_IO, "This operation is not supported. (%s)", dlerror());
334 r = E_UNSUPPORTED_OPERATION;
338 ret = sqlite3_key_func(pDb, pDbKey.get(), MAX_DATABASE_AES_KEY_LENGTH * 2);
341 if (ret != SQLITE_OK)
343 r = __ConvertNativeSqliteErrorToResult(ret);
344 SysLog(NID_IO, "[%s] sqlite3_key() failed (%d, %s).", GetErrorMessage(r), ret, sqlite3_errmsg(pDb));
359 _DatabaseImpl::Construct(const String& dbPath, const char* pOpenMode, const ByteBuffer* pSecretKey)
361 SysAssertf(__pDatabase == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class\n");
362 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(dbPath, _AppInfo::IsOspCompat()) == true,
363 E_INVALID_ARG, "The specified dbPath (%ls) is invalid.", dbPath.GetPointer());
364 SysTryReturnResult(NID_IO, !(pSecretKey && pSecretKey->GetRemaining() <= 0), E_INVALID_ARG,
365 "The specified secretKey is invalid.");
368 bool isValidOpenMode = _DatabaseImpl::VerifyDatabaseOpenMode(pOpenMode, legacyMode);
369 SysTryReturnResult(NID_IO, isValidOpenMode == true, E_INVALID_ARG, "The specified openMode is invalid. (%s)", pOpenMode);
374 bool isFilePathExist = false;
375 bool isParentDirPathExist = false;
377 String parentDirPath;
381 case DB_OPEN_READ_WRITE:
382 openFlags = SQLITE_OPEN_READWRITE;
384 case DB_OPEN_READ_ONLY:
385 openFlags = SQLITE_OPEN_READONLY;
387 case (DB_OPEN_READ_WRITE | DB_OPEN_CREATE):
388 openFlags = (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
391 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
392 return E_INVALID_ARG;
395 // extract directory path from a given Db file path
396 // Find index of last occurrence of character '/' in dbPath
397 result r = dbPath.LastIndexOf(L'/', dbPath.GetLength() - 1, lastIndex);
398 SysTryReturnResult(NID_IO, !IsFailed(r), E_INVALID_ARG,
399 "Missing directory path. SHOULD not happen.");
401 // extract directory path from dbPath starting from index 0 to lastIndex.
402 r = dbPath.SubString(0, lastIndex, parentDirPath);
403 SysTryReturnResult(NID_IO, !IsFailed(r), E_INVALID_ARG,
404 "Missing directory path. SHOULD not happen.");
406 // TODO: Test sqlite3_open_v3() without parent directory.
407 //check existence of parent directory
408 isParentDirPathExist = _FileImpl::IsFileExist(String(parentDirPath));
409 SysTryReturnResult(NID_IO, isParentDirPathExist == true, E_INVALID_ARG,
410 "Parent Directory dose not exist.");
412 unique_ptr<char[]> pDbPath(_StringConverter::CopyToCharArrayN(dbPath));
413 SysTryReturn(NID_IO, pDbPath, GetLastResult(), GetLastResult(), "[%s] pDbPath is null.", GetErrorMessage(GetLastResult()));
415 //check existence of file
416 isFilePathExist = _FileImpl::IsFileExist(dbPath);
417 if (isFilePathExist == true)
419 //check if it is a directory
420 SysTryReturnResult(NID_IO, !IsDirectory(dbPath), E_INVALID_ARG, "Given path is not a File.");
423 _DatabaseMode dbMode = DATABASE_MODE_NONE;
424 dbMode = _SecureIoUtil::GetDatabaseMode(pDbPath.get());
425 SysTryReturnResult(NID_IO, dbMode != DATABASE_MODE_ERROR, E_INVALID_FORMAT,
426 "GetDatabaseMode function failed.");
428 if (pSecretKey && _SecureIoUtil::IsNormalDatabase(dbMode))
430 SysTryReturnResult(NID_IO, false, E_INVALID_ARG,
431 "Trying to open a normal database in secure mode.");
433 else if (!pSecretKey && _SecureIoUtil::IsSecureDatabase(dbMode))
435 SysTryReturnResult(NID_IO, false, E_INVALID_ARG,
436 "Trying to open a secure database in normal mode.");
446 if (legacyMode == DB_OPEN_READ_WRITE || legacyMode == DB_OPEN_READ_ONLY)
448 SysLog(NID_IO, "[E_FILE_NOT_FOUND] File not found.");
449 r = E_FILE_NOT_FOUND;
454 // open/create the database
455 ret = sqlite3_open_v2(pDbPath.get(), &pDb, openFlags, null);
456 if (ret != SQLITE_OK)
458 if (!_AppInfo::IsOspCompat())
460 r = __ConvertNativeSqliteErrorToDetailResult(ret);
464 case E_OBJECT_LOCKED:
465 case E_INVALID_OPERATION:
473 r = __ConvertNativeSqliteErrorToResult(ret);
476 SysLog(NID_IO, "[%s] Failed to open database file (%s). (%d, %s).", GetErrorMessage(r), pDbPath.get(),
477 ret, sqlite3_errmsg(static_cast< sqlite3* >(pDb)));
483 unique_ptr<byte[]> pDbKey(_SecureIoUtil::GenerateDatabaseKeyN(pSecretKey));
484 SysTryReturnResult(NID_IO, pDbKey != null, E_IO, "GenerateDatabaseKeyN returned null.");
488 r = SystemInfo::GetValue(L"http://tizen.org/feature/database.encryption", secure);
489 SysTryReturnResult(NID_IO, !IsFailed(r), E_SYSTEM, "The method cannot proceed due to a severe system error.");
490 SysTryReturnResult(NID_IO, secure == true, E_UNSUPPORTED_OPERATION, "This operation is not supported.");
492 ret = sqlite3_key(pDb, pDbKey.get(), MAX_DATABASE_AES_KEY_LENGTH * 2);
494 int (* sqlite3_key_func)(sqlite3*, const void*, int) = null;
495 void* handle = dlopen(_DATABASE_LIBRARY_PATH, RTLD_LAZY | RTLD_LOCAL);
496 SysTryReturnResult(NID_IO, handle != null, E_SYSTEM,
497 "Failed to dlopen database library file (%s)", dlerror());
499 sqlite3_key_func = reinterpret_cast< int (*)(sqlite3*, const void*, int) >(dlsym(handle, _DATABASE_ENCRYPTION_SYMBOL));
500 if (sqlite3_key_func == null)
502 SysLog(NID_IO, "This operation is not supported. (%s)", dlerror());
504 r = E_UNSUPPORTED_OPERATION;
508 ret = sqlite3_key_func(pDb, pDbKey.get(), MAX_DATABASE_AES_KEY_LENGTH * 2);
511 if (ret != SQLITE_OK)
513 if (!_AppInfo::IsOspCompat())
522 SysLog(NID_IO, "[%s] Failed to create secret key (%d, %s).", GetErrorMessage(r), ret,
523 sqlite3_errmsg(static_cast< sqlite3* >(pDb)));
538 _DatabaseImpl::CreateStatementN(const String& statement)
540 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
543 char* pStrStmt = null;
544 sqlite3_stmt* pSqlStmt = null;
545 result r = E_SUCCESS;
547 unique_ptr<DbStatement> pDbStatement(_DbStatementImpl::CreateDbStatementInstanceN());
549 SysTryReturn(NID_IO, pDbStatement != null, null, E_OUT_OF_MEMORY,
550 "[E_OUT_OF_MEMORY] The memory is insufficient.");
552 unique_ptr<char[]> pUnTrimStatement(_StringConverter::CopyToCharArrayN(statement));
553 if (pUnTrimStatement == null)
559 // trim leading spaces
560 pStrStmt = pUnTrimStatement.get();
561 while ((*pStrStmt == ' ') || (*pStrStmt == '\t'))
566 // prepare the sql statement
567 ret = sqlite3_prepare_v2((sqlite3*) __pDatabase, pStrStmt, strlen(pStrStmt), &pSqlStmt, null);
568 if (ret != SQLITE_OK)
570 if (!_AppInfo::IsOspCompat())
572 r = __ConvertNativeSqliteErrorToDetailResult(ret);
575 case E_ILLEGAL_ACCESS:
577 case E_INVALID_FORMAT:
579 case E_INVALID_OPERATION:
587 r = __ConvertNativeSqliteErrorToResult(ret);
590 SysLog(NID_IO, "[%s] Failed to prepare SQL statement (%s). (%d, %s).", GetErrorMessage(r), pStrStmt,
591 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
595 // register the sql stmt in DbStatement
596 // accessing private variable of DbStatement.
597 _DbStatementImpl::GetInstance(*pDbStatement)->__pStmt = pSqlStmt;
598 _DbStatementImpl::GetInstance(*pDbStatement)->__pDatabase = __pDatabase;
600 // "SELECT" or other statement?
601 if (strncasecmp(pStrStmt, "select", 5) == 0)
603 _DbStatementImpl::GetInstance(*pDbStatement)->__stmtType = DB_STATEMENT_TYPE_SELECT;
607 _DbStatementImpl::GetInstance(*pDbStatement)->__stmtType = DB_STATEMENT_TYPE_OTHER;
611 return pDbStatement.release();
619 _DatabaseImpl::ExecuteStatementN(const DbStatement& statement)
621 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
622 SysTryReturn(NID_IO, _DbStatementImpl::GetInstance(statement)->__pStmt != null, null, E_INVALID_ARG,
623 "[E_INVALID_ARG] Invalid DbStatement was passed.(null handle was assigned)");
626 DbEnumerator* pDbEnum = null;
627 result r = E_SUCCESS;
629 ret = sqlite3_reset((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
630 if (ret != SQLITE_OK)
632 if (!_AppInfo::IsOspCompat())
634 r = __ConvertNativeSqliteErrorToDetailResult(ret);
638 case E_ILLEGAL_ACCESS:
640 case E_INVALID_FORMAT:
642 case E_INVALID_OPERATION:
650 r = __ConvertNativeSqliteErrorToResult(ret);
653 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
654 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
659 ret = sqlite3_step((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
664 ret = sqlite3_reset((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
665 if (ret != SQLITE_OK)
667 if (!_AppInfo::IsOspCompat())
669 r = __ConvertNativeSqliteErrorToDetailResult(ret);
673 case E_ILLEGAL_ACCESS:
675 case E_INVALID_FORMAT:
677 case E_INVALID_OPERATION:
685 r = __ConvertNativeSqliteErrorToResult(ret);
688 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
689 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
695 if (_DbStatementImpl::GetInstance(statement)->__stmtType == DB_STATEMENT_TYPE_SELECT)
697 unique_ptr<DbEnumerator> pTempDbEnum(_DbEnumeratorImpl::CreateDbEnumeratorInstanceN());
699 SysTryReturn(NID_IO, pTempDbEnum != null, null, E_OUT_OF_MEMORY,
700 "[E_OUT_OF_MEMORY] The memory is insufficient.");
702 _DbEnumeratorImpl::GetInstance(*pTempDbEnum)->__pEnum = _DbStatementImpl::GetInstance(statement)->__pStmt;
703 _DbEnumeratorImpl::GetInstance(*pTempDbEnum)->__pDatabase = _DbStatementImpl::GetInstance(statement)->__pDatabase;
706 ret = sqlite3_reset((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
707 if (ret != SQLITE_OK)
709 if (!_AppInfo::IsOspCompat())
711 r = __ConvertNativeSqliteErrorToDetailResult(ret);
715 case E_ILLEGAL_ACCESS:
717 case E_INVALID_FORMAT:
719 case E_INVALID_OPERATION:
727 r = __ConvertNativeSqliteErrorToResult(ret);
730 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
731 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
736 pDbEnum = pTempDbEnum.release();
741 goto REDO_SQLITE_STEP;
746 if (!_AppInfo::IsOspCompat())
748 r = __ConvertNativeSqliteErrorToDetailResult(ret);
751 case E_ILLEGAL_ACCESS:
752 case E_INVALID_OPERATION:
760 r = __ConvertNativeSqliteErrorToResult(ret);
763 SysLog(NID_IO, "[%s] Failed to execute SQL statement. (%d, %s).", GetErrorMessage(r), ret,
764 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
768 SetLastResult(E_SUCCESS);
777 _DatabaseImpl::ExecuteSql(const String& sql, bool autoCommit)
779 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
782 char* pSqlStr = null;
783 result r = E_SUCCESS;
785 unique_ptr<char[]> pUnTrimStatement(_StringConverter::CopyToCharArrayN(sql));
786 if (pUnTrimStatement == null)
792 // trim leading spaces
793 pSqlStr = pUnTrimStatement.get();
794 while ((*pSqlStr == ' ') || (*pSqlStr == '\t'))
799 // "SELECT" or other statement?
800 if (strncasecmp(pSqlStr, "select", 5) == 0)
802 r = E_INVALID_OPERATION;
806 ret = sqlite3_exec((sqlite3*) __pDatabase, pSqlStr, null, null, null);
807 if (ret != SQLITE_OK)
809 if (!_AppInfo::IsOspCompat())
811 r = __ConvertNativeSqliteErrorToDetailResult(ret);
814 case E_ILLEGAL_ACCESS:
815 case E_INVALID_OPERATION:
823 r = __ConvertNativeSqliteErrorToResult(ret);
826 SysLog(NID_IO, "[%s] Failed to execute SQL statement. (%d, %s).", GetErrorMessage(r), ret,
827 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
838 _DatabaseImpl::QueryN(const String& query)
840 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
844 sqlite3_stmt* pSqlStmt = null;
845 unique_ptr<DbEnumerator> pDbEnum(null);
846 result r = E_SUCCESS;
848 unique_ptr<char[]> pUnTrimStatement(_StringConverter::CopyToCharArrayN(query));
849 if (pUnTrimStatement == null)
855 // trim leading spaces
856 pQuery = pUnTrimStatement.get();
857 while ((*pQuery == ' ') || (*pQuery == '\t'))
862 // "SELECT" or other statement?
863 if (strncasecmp(pQuery, "select", 5) != 0)
865 r = E_INVALID_OPERATION;
869 // prepare the sql statement
870 ret = sqlite3_prepare_v2((sqlite3*) __pDatabase, pQuery, strlen(pQuery), &pSqlStmt, null);
871 if (ret != SQLITE_OK)
873 if (!_AppInfo::IsOspCompat())
875 r = __ConvertNativeSqliteErrorToDetailResult(ret);
878 case E_ILLEGAL_ACCESS:
880 case E_INVALID_FORMAT:
882 case E_INVALID_OPERATION:
890 r = __ConvertNativeSqliteErrorToResult(ret);
893 SysLog(NID_IO, "[%s] Failed to prepare SQL statement (%s). (%d, %s).", GetErrorMessage(r), pQuery,
894 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
898 // ret = sqlite3_reset((sqlite3_stmt *) pSqlStmt);
899 // if (ret != SQLITE_OK)
901 // r = __ConvertNativeSqliteErrorToResult(ret);
902 // SysLog(NID_IO, "[_DatabaseImpl] ERROR: [%s] Failed to reset SQL statement.", GetErrorMessage(r));
906 ret = sqlite3_step(pSqlStmt);
914 pDbEnum.reset(_DbEnumeratorImpl::CreateDbEnumeratorInstanceN());
916 SysTryCatch(NID_IO, pDbEnum != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
917 "[E_OUT_OF_MEMORY] The memory is insufficient.");
919 _DbEnumeratorImpl::GetInstance(*pDbEnum)->__pEnum = pSqlStmt;
920 _DbEnumeratorImpl::GetInstance(*pDbEnum)->__pDatabase = __pDatabase;
921 _DbEnumeratorImpl::GetInstance(*pDbEnum)->__shouldReleaseResource = true;
923 // doing a reset again, so that enumerator first MoveNext() give the first row.
924 ret = sqlite3_reset((sqlite3_stmt*) pSqlStmt);
925 if (ret != SQLITE_OK)
927 if (!_AppInfo::IsOspCompat())
929 r = __ConvertNativeSqliteErrorToDetailResult(ret);
933 case E_ILLEGAL_ACCESS:
935 case E_INVALID_FORMAT:
937 case E_INVALID_OPERATION:
945 r = __ConvertNativeSqliteErrorToResult(ret);
948 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
949 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
955 if (!_AppInfo::IsOspCompat())
957 r = __ConvertNativeSqliteErrorToDetailResult(ret);
960 case E_ILLEGAL_ACCESS:
962 case E_INVALID_OPERATION:
970 r = __ConvertNativeSqliteErrorToResult(ret);
973 SysLog(NID_IO, "[%s] Failed to exectue SQL statement (%s). (%d, %s).", GetErrorMessage(r), pQuery,
974 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
979 return pDbEnum.release();
982 sqlite3_finalize(pSqlStmt);
988 _DatabaseImpl::BeginTransaction(void)
990 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
991 SysTryReturnResult(NID_IO, __transactionGoingOn == false, E_INVALID_STATE,
992 "A transaction is already in progress.");
994 result r = E_SUCCESS;
996 if (sqlite3_get_autocommit((sqlite3*) __pDatabase) == 0)
998 SysLog(NID_IO, "[E_INVALID_STATE] Already in transaction mode.");
999 return E_INVALID_STATE;
1002 int ret = sqlite3_exec((sqlite3*) __pDatabase, "BEGIN", null, null, null);
1003 if (ret != SQLITE_OK)
1005 if (!_AppInfo::IsOspCompat())
1007 r = __ConvertNativeSqliteErrorToDetailResult(ret);
1011 case E_ILLEGAL_ACCESS:
1012 case E_OBJECT_LOCKED:
1014 case E_INVALID_FORMAT:
1015 case E_STORAGE_FULL:
1016 case E_INVALID_OPERATION:
1023 r = __ConvertNativeSqliteErrorToResult(ret);
1026 SysLog(NID_IO, "[%s] Failed to begin transaction. (%d, %s)", GetErrorMessage(r), ret,
1027 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
1031 __transactionGoingOn = true;
1038 _DatabaseImpl::CommitTransaction(void)
1040 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1041 SysTryReturnResult(NID_IO, __transactionGoingOn == true, E_INVALID_STATE,
1042 "A transaction is already in progress.");
1045 result r = E_SUCCESS;
1047 if (sqlite3_get_autocommit((sqlite3*) __pDatabase) != 0)
1049 SysLog(NID_IO, "[E_INVALID_STATE] ERROR Message: Not in transaction mode.");
1050 return E_INVALID_STATE;
1053 ret = sqlite3_exec((sqlite3*) __pDatabase, "COMMIT", null, null, null);
1054 if (ret != SQLITE_OK)
1056 if (!_AppInfo::IsOspCompat())
1058 r = __ConvertNativeSqliteErrorToDetailResult(ret);
1062 case E_ILLEGAL_ACCESS:
1063 case E_INVALID_OPERATION:
1070 r = __ConvertNativeSqliteErrorToResult(ret);
1073 SysLog(NID_IO, "[%s] Failed to commit transaction. (%d, %s)", GetErrorMessage(r), ret,
1074 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
1078 __transactionGoingOn = false;
1085 _DatabaseImpl::RollbackTransaction(void)
1087 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1088 SysTryReturnResult(NID_IO, __transactionGoingOn == true, E_INVALID_STATE,
1089 "No transaction in progress.");
1092 result r = E_SUCCESS;
1094 if (sqlite3_get_autocommit((sqlite3*) __pDatabase) != 0)
1096 SysLog(NID_IO, "[E_SUCCESS] No transaction in progress.");
1097 //return E_INVALID_STATE;
1101 ret = sqlite3_exec((sqlite3*) __pDatabase, "ROLLBACK", null, null, null);
1102 if (ret != SQLITE_OK)
1104 if (!_AppInfo::IsOspCompat())
1106 r = __ConvertNativeSqliteErrorToDetailResult(ret);
1110 case E_ILLEGAL_ACCESS:
1111 case E_INVALID_OPERATION:
1118 r = __ConvertNativeSqliteErrorToResult(ret);
1121 SysLog(NID_IO, "[%s] Failed to rollback the transaction. (%d, %s)", GetErrorMessage(r), ret,
1122 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
1126 __transactionGoingOn = false;
1133 _DatabaseImpl::GetName(void) const
1135 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1137 SetLastResult(E_SUCCESS);
1142 _DatabaseImpl::RegisterUserFunction(const String& functionName, const int argumentCount, void* pUserData,
1143 _IDbUserFunctionListener* pUserFunctionListener,
1144 _IDbUserAggregateListener* pUserAggregateListener)
1146 result r = E_SUCCESS;
1147 int sqliteEncoding = 0;
1150 unique_ptr<_DbContextImpl> pDbContext(null);
1151 _DbContextImpl* pTempDbContext = null;
1152 bool entryFound = false;
1155 // Validate input parameters
1156 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1157 SysTryReturnResult(NID_IO, functionName.GetLength() > 0, E_INVALID_ARG,
1158 "Invalid funcName length.");
1159 SysTryReturnResult(NID_IO, argumentCount >= 0 && argumentCount <= MAX_FUNCTION_ARGUMENT_COUNT, E_INVALID_ARG,
1160 "argumentCount < 0 or > 127.");
1162 if (pUserFunctionListener != null && pUserAggregateListener != null)
1164 SysTryReturnResult(NID_IO, 0, E_INVALID_ARG,
1165 "FunctionListener and AggregateListener cannot be registered together");
1168 //select the equivalent sqlite encoding.
1170 unique_ptr<ByteBuffer> pFuncNameBuf(StringUtil::StringToUtf8N(functionName));
1171 SysTryReturn(NID_IO, pFuncNameBuf != null, GetLastResult(),
1172 GetLastResult(), "[%s] Invalid Function name.", GetErrorMessage(GetLastResult()));
1174 utf8len = pFuncNameBuf->GetLimit();
1175 SysTryReturnResult(NID_IO, utf8len > 0 && utf8len <= MAX_UTF8_BYTES, E_INVALID_ARG,
1176 "functionName length in utf8 bytes should be >0 && <=255.");
1178 sqliteEncoding = SQLITE_UTF8; // support only UTF8
1180 //check if the (FunctionName, argumentCount) already exist in the list
1181 for (i = 0; i < __userFunctionContextList.GetCount(); i++)
1183 pTempDbContext = dynamic_cast<_DbContextImpl*> (__userFunctionContextList.GetAt(i));
1184 SysTryReturnResult(NID_IO, pTempDbContext, E_IO, "The __userFunctionContextList has an invalid element.");
1185 if ((pTempDbContext->__argumentCount == argumentCount) &&
1186 (pTempDbContext->__functionName == functionName))
1193 if (entryFound && (null != pUserFunctionListener || null != pUserAggregateListener))
1195 SysTryReturnResult(NID_IO, 0, E_INVALID_ARG,
1196 "(functionName, argumentCount) already registered");
1199 if (pUserFunctionListener != null) // register FunctionListener
1201 pDbContext.reset(new (std::nothrow) _DbContextImpl());
1202 SysTryReturnResult(NID_IO, pDbContext != null, E_OUT_OF_MEMORY,
1203 "The memory is insufficient.");
1205 ret = sqlite3_create_function((sqlite3*) __pDatabase,
1206 (const char*) pFuncNameBuf->GetPointer(), argumentCount, sqliteEncoding, pDbContext.get(),
1207 _DatabaseImpl::UserFunctionListener, null, null);
1209 else if (pUserAggregateListener != null) // register both FunctionStepListener and FunctionFinalListener
1211 pDbContext.reset(new (std::nothrow) _DbContextImpl());
1213 SysTryReturnResult(NID_IO, pDbContext != null, E_OUT_OF_MEMORY,
1214 "The memory is insufficient.");
1216 ret = sqlite3_create_function((sqlite3*) __pDatabase,
1217 (const char*) pFuncNameBuf->GetPointer(), argumentCount, sqliteEncoding, pDbContext.get(),
1218 null, _DatabaseImpl::UserFunctionStepListener, _DatabaseImpl::UserFunctionFinalListener);
1220 else // Delete registered user function/Aggregate
1222 ret = sqlite3_create_function((sqlite3*) __pDatabase,
1223 (const char*) pFuncNameBuf->GetPointer(), argumentCount, sqliteEncoding, null, null, null, null);
1226 if (ret != SQLITE_OK) //error
1228 r = __ConvertNativeSqliteErrorToResult(ret);
1229 SysLog(NID_IO, "[%s] ERROR Message: [%s], Failed to create/delete user defined SQL function.", GetErrorMessage(r),
1230 sqlite3_errmsg((sqlite3*)__pDatabase));
1234 if (entryFound && (!pUserFunctionListener && !pUserAggregateListener)) // delete the user function entry from list
1236 r = __userFunctionContextList.Remove(*pTempDbContext, true);
1237 SysTryReturn(NID_IO, !IsFailed(r), GetLastResult(),
1238 GetLastResult(), "[%s] Failed to remove user function context to the list.", GetErrorMessage(GetLastResult()));
1241 if (pDbContext != null)
1243 //store listener and user data
1244 pDbContext->__pUserData = pUserData;
1245 pDbContext->__argumentCount = argumentCount;
1246 pDbContext->__functionName = functionName;
1247 if (pUserFunctionListener != null)
1249 pDbContext->__pUserFunctionListener = pUserFunctionListener;
1251 if (pUserAggregateListener != null)
1253 pDbContext->__pUserAggregateListener = pUserAggregateListener;
1256 // add entry to the list
1257 r = __userFunctionContextList.Add(*(pDbContext.release()));
1258 SysTryReturn(NID_IO, !IsFailed(r), GetLastResult(),
1259 GetLastResult(), "[%s] Failed to add user function context to the list.", GetErrorMessage(GetLastResult()));
1266 _DatabaseImpl::RegisterUserCollation(const String& collationName, void* pUserData,
1267 _IDbUserCollationListener* pUserCollationListener)
1269 result r = E_SUCCESS;
1270 int sqliteEncoding = 0;
1273 unique_ptr<_DbContextImpl> pDbContext(null);
1274 _DbContextImpl* pTempDbContext = null;
1275 bool entryFound = false;
1278 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1279 SysTryReturnResult(NID_IO, collationName.GetLength() > 0, E_INVALID_ARG,
1280 "Invalid collationName length.");
1282 sqliteEncoding = SQLITE_UTF8; // support only UTF8
1284 unique_ptr<ByteBuffer> pColNameBuf(StringUtil::StringToUtf8N(collationName));
1285 SysTryReturn(NID_IO, pColNameBuf != null, GetLastResult(), GetLastResult(), "[%s] Invalid Function name.",
1286 GetErrorMessage(GetLastResult()));
1288 utf8len = pColNameBuf->GetLimit(); // get UTF_8 bytes length
1289 SysTryReturnResult(NID_IO, utf8len > 0 && utf8len <= MAX_UTF8_BYTES, E_INVALID_ARG,
1290 "functionName length in utf8 bytes should be >0 && <=255.");
1292 //check if the (FunctionName) already registered
1293 for (i = 0; i < __userCollationContextList.GetCount(); i++)
1295 pTempDbContext = dynamic_cast< _DbContextImpl* >(__userCollationContextList.GetAt(i));
1296 SysTryReturnResult(NID_IO, pTempDbContext, E_IO, "The __userCollationContextList has an invalid element.");
1297 if (pTempDbContext->__collationName == collationName)
1304 if (entryFound && (pUserCollationListener != null)) // check if the operation is to delete the user function
1306 SysTryReturnResult(NID_IO, 0, E_INVALID_ARG, "(collationName) already registered");
1309 if (pUserCollationListener != null)
1311 pDbContext.reset(new (std::nothrow) _DbContextImpl());
1312 SysTryReturnResult(NID_IO, pDbContext != null, E_OUT_OF_MEMORY,
1313 "The memory is insufficient.");
1315 // register CollationListener()
1316 ret = sqlite3_create_collation((sqlite3*) __pDatabase, (const char*) pColNameBuf->GetPointer(), sqliteEncoding, pDbContext.get(),
1317 _DatabaseImpl::UserCollationListener);
1319 else // delete Collating function
1321 ret = sqlite3_create_collation((sqlite3*) __pDatabase, (const char*) pColNameBuf->GetPointer(), sqliteEncoding, null, null);
1324 if (ret != SQLITE_OK)
1326 r = __ConvertNativeSqliteErrorToResult(ret);
1327 SysLog(NID_IO, "[%s] ERROR Message: [%s], Failed to create/delete user defined SQL Collation.", GetErrorMessage(r),
1328 sqlite3_errmsg((sqlite3*)__pDatabase));
1332 if (entryFound && !pUserCollationListener) // delete the user collation entry from list
1334 r = __userCollationContextList.Remove(*pTempDbContext, true);
1335 SysTryReturn(NID_IO, !IsFailed(r), GetLastResult(),
1336 GetLastResult(), "[%s] Failed to remove user collation context from the list.", GetErrorMessage(GetLastResult()));
1339 if (pDbContext != null)
1341 //store listener and user data
1342 pDbContext->__pUserData = pUserData;
1343 pDbContext->__collationName = collationName;
1344 pDbContext->__pUserCollationListener = pUserCollationListener;
1345 // add entry to the list
1346 r = __userCollationContextList.Add((*(pDbContext.release())));
1347 SysTryReturn(NID_IO, !IsFailed(r), GetLastResult(),
1348 GetLastResult(), "[%s] Failed to add user collation context to the list.", GetErrorMessage(GetLastResult()));
1356 _DatabaseImpl::GetLastInsertRowId(void) const
1358 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1360 // Retrieve last inserted row Id of the specified Db connection.
1361 // sqlite rowIds starts from 1 to max. 0 means no rows available in the database.
1362 // even if we delete the last inserted row, it still returns the rowid of last insert.
1363 // and does not care about any deletions happened.
1364 long long insertRowId = sqlite3_last_insert_rowid(static_cast< sqlite3* >(__pDatabase));
1365 if (insertRowId == 0)
1376 _DatabaseImpl::Delete(const String& databasePath)
1378 result r = E_SUCCESS;
1381 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(databasePath, _AppInfo::IsOspCompat()) == true,
1382 E_INVALID_ARG, " [%ls] is not compatible.", databasePath.GetPointer());
1384 unique_ptr<char[]> pDbPath(_StringConverter::CopyToCharArrayN(databasePath));
1385 if (pDbPath == null)
1387 return GetLastResult();
1391 ret = unlink(pDbPath.get());
1394 r = __ConvertNativeErrorToResult(errno);
1401 _DatabaseImpl::Exists(const String& databasePath)
1403 return _FileImpl::IsFileExist(databasePath);
1407 _DatabaseImpl::UserFunctionListener(sqlite3_context* pContext, int argumentCount, sqlite3_value** pArgList)
1409 _DbContextImpl* pDbContext = null;
1411 pDbContext = static_cast< _DbContextImpl* >(sqlite3_user_data(pContext));
1413 SysTryReturnVoidResult(NID_IO, pDbContext, E_INVALID_STATE, "[E_INVALID_STATE] pDbContext is null.");
1414 SysTryReturnVoidResult(NID_IO, pDbContext->__pUserFunctionListener, E_INVALID_STATE,
1415 "[E_INVALID_STATE] UserAggregateListener is null.");
1417 //Set DbContext data
1418 if (pDbContext->__pContext != (void*) pContext)
1420 pDbContext->__pContext = (void*) pContext;
1423 if (pDbContext->__argumentCount != argumentCount)
1425 SysLog(NID_IO, "Message: __argumentCount mismatch.");
1426 pDbContext->__argumentCount = argumentCount;
1429 if (pDbContext->__pArgList != (void**) pArgList)
1431 pDbContext->__pArgList = (void**) pArgList;
1433 // Invoke the user listener method
1434 pDbContext->__pUserFunctionListener->OnDbUserFunction(*pDbContext, argumentCount);
1436 SetLastResult(E_SUCCESS);
1440 _DatabaseImpl::UserFunctionStepListener(sqlite3_context* pContext, int argumentCount, sqlite3_value** pArgList)
1442 _DbContextImpl* pDbContext = null;
1444 pDbContext = static_cast< _DbContextImpl* >(sqlite3_user_data(pContext));
1446 SysTryReturnVoidResult(NID_IO, pDbContext, E_INVALID_STATE, "[E_INVALID_STATE] pDbContext is null.");
1447 SysTryReturnVoidResult(NID_IO, pDbContext->__pUserAggregateListener, E_INVALID_STATE,
1448 "[E_INVALID_STATE] __pDbContextImpl->__pUserAggregateListener is null.");
1450 //Set DbContext data
1451 if (pDbContext->__pContext != (void*) pContext)
1453 pDbContext->__pContext = (void*) pContext;
1456 if (pDbContext->__argumentCount != argumentCount)
1458 pDbContext->__argumentCount = argumentCount;
1461 if (pDbContext->__pArgList != (void**) pArgList)
1463 pDbContext->__pArgList = (void**) pArgList;
1466 // invoke the user listener method
1467 pDbContext->__pUserAggregateListener->OnDbUserAggregateStep(*pDbContext, argumentCount);
1469 SetLastResult(E_SUCCESS);
1473 _DatabaseImpl::UserFunctionFinalListener(sqlite3_context* pContext)
1475 _DbContextImpl* pDbContext = null;
1477 pDbContext = static_cast< _DbContextImpl* >(sqlite3_user_data(pContext));
1479 SysTryReturnVoidResult(NID_IO, pDbContext, E_INVALID_STATE, "[E_INVALID_STATE] pDbContext is null.");
1480 SysTryReturnVoidResult(NID_IO, pDbContext->__pUserAggregateListener, E_INVALID_STATE,
1481 "[E_INVALID_STATE] UserAggregateListener is null.");
1483 // set context and user data
1484 if (pDbContext->__pContext != (void*) pContext)
1486 pDbContext->__pContext = (void*) pContext;
1489 // invoke the user listener method
1490 pDbContext->__pUserAggregateListener->OnDbUserAggregateFinal(*pDbContext);
1492 SetLastResult(E_SUCCESS);
1496 _DatabaseImpl::UserCollationListener(void* pUserData, int length1, const void* pInput1, int length2, const void* pInput2)
1498 _DbContextImpl* pDbContext = null;
1499 char* pDataInput = null;
1503 pDbContext = static_cast< _DbContextImpl* >(pUserData);
1505 SysTryReturn(NID_IO, pDbContext, 0, E_INVALID_STATE, "[E_INVALID_STATE] pDbContext is null.");
1506 SysTryReturn(NID_IO, pDbContext->__pUserCollationListener, 0, E_INVALID_STATE,
1507 "[E_INVALID_STATE] UserCollationListener is null.");
1509 if (length1 > 0 && (const char*) pInput1 != null)
1511 pDataInput = (char*) malloc((length1 + 1) * sizeof(char));
1513 if (pDataInput == null)
1518 memset(pDataInput, 0, length1 + 1);
1519 strncpy(pDataInput, (const char*) pInput1, length1);
1521 string1.Append((const char*) pDataInput);
1525 if (length2 > 0 && (const char*) pInput2 != null)
1527 pDataInput = (char*) malloc((length2 + 1) * sizeof(char));
1529 if (pDataInput == null)
1534 memset(pDataInput, 0, length2 + 1);
1535 strncpy(pDataInput, (const char*) pInput2, length2);
1537 string2.Append((const char*) pDataInput);
1541 SetLastResult(E_SUCCESS);
1543 return pDbContext->__pUserCollationListener->OnDbUserCollation(string1, string2, pUserData);
1547 _DatabaseImpl::ConvertToSecureDatabase(const String& plainDbPath, const String& secureDbPath, const ByteBuffer* pKey)
1549 result r = E_SUCCESS;
1551 String parentDirPath;
1552 FileAttributes attr;
1554 if (Database::Exists(secureDbPath))
1556 if (GetLastResult() == E_SUCCESS)
1558 r = File::GetAttributes(secureDbPath, attr);
1561 if (attr.IsDirectory())
1563 return E_INVALID_ARG;
1567 return E_FILE_ALREADY_EXIST;
1581 unique_ptr<Database>pDatabase(new (std::nothrow) Database());
1582 SysTryReturnResult(NID_IO, pDatabase, E_OUT_OF_MEMORY, "The memory is insufficient.");
1584 r = pDatabase->Construct(secureDbPath, "a+");
1585 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1587 pDatabase.reset(new (std::nothrow) Database());
1588 SysTryReturnResult(NID_IO, pDatabase, E_OUT_OF_MEMORY, "The memory is insufficient.");
1590 r = pDatabase->Construct(plainDbPath, "r+");
1591 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1593 unique_ptr<String> pSqlStr(new (std::nothrow) String(MAX_DATABASE_SQL_LENGTH));
1594 SysTryReturnResult(NID_IO, pSqlStr != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1596 unique_ptr<char[]> pPhysicalDbPath(_StringConverter::CopyToCharArrayN(secureDbPath));
1597 SysTryReturn(NID_IO, pPhysicalDbPath != null, GetLastResult(), GetLastResult(), "[%s] Invalid file path.", GetErrorMessage(GetLastResult()));
1599 unique_ptr<byte[]> pDbKey(_SecureIoUtil::GenerateDatabaseKeyN(pKey));
1600 SysTryReturnResult(NID_IO, pDbKey != null, E_INVALID_ARG, "GenerateDatabaseKeyN returned null.");
1602 pSqlStr->Format(MAX_DATABASE_SQL_LENGTH, L"ATTACH DATABASE '%s' AS encrypted KEY '%s'", pPhysicalDbPath.get(), pDbKey.get());
1604 sql.Append(*pSqlStr);
1605 r = pDatabase->ExecuteSql(sql, true);
1606 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1609 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"));
1610 r = GetLastResult();
1616 String tempQuery(L"encrypted.");
1618 while (pEnum->MoveNext() == E_SUCCESS)
1620 r = pEnum->GetStringAt(0, schema);
1623 if (r == E_INVALID_STATE || r == E_TYPE_MISMATCH || r == E_INVALID_ENCODING_RANGE) //internal exception by this method
1630 if (schema.StartsWith(L"sqlite_", MAX_SQLCIPHER_SCHEMA_PREFIX_SIZE))
1635 r = schema.Insert(tempQuery, MAX_SQLCIPHER_SCHEMA_PREFIX_SIZE);
1641 r = pDatabase->ExecuteSql(schema, true);
1642 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to caller...", GetErrorMessage(r));
1648 SysPropagate(NID_IO, r);
1652 pEnum.reset(pDatabase->QueryN(L"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"));
1653 r = GetLastResult();
1659 while (pEnum->MoveNext() == E_SUCCESS)
1661 r = pEnum->GetStringAt(0, tableName);
1664 if (r == E_INVALID_STATE || r == E_TYPE_MISMATCH || r == E_INVALID_ENCODING_RANGE) //internal exception by this method
1672 if (tableName.StartsWith(L"sqlite_", 0))
1677 pSqlStr.reset(new (std::nothrow) String(MAX_DATABASE_SQL_LENGTH));
1678 SysTryReturnResult(NID_IO, pSqlStr, E_OUT_OF_MEMORY, "The memory is insufficient.");
1680 pSqlStr->Format(MAX_DATABASE_SQL_LENGTH, L"INSERT INTO encrypted.%ls SELECT * FROM %ls", tableName.GetPointer(), tableName.GetPointer());
1682 sql.Append(*pSqlStr);
1683 r = pDatabase->ExecuteSql(sql, true);
1684 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1691 SysPropagate(NID_IO, r);
1695 sql.Append(L"DETACH DATABASE encrypted");
1697 r = pDatabase->ExecuteSql(sql, true);
1698 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1704 _DatabaseImpl::GetInstance(Database& database)
1706 return database.__pDatabaseImpl;
1709 const _DatabaseImpl*
1710 _DatabaseImpl::GetInstance(const Database& database)
1712 return database.__pDatabaseImpl;