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 if (strncasecmp(pStrStmt, "select", 6) == 0)
602 _DbStatementImpl::GetInstance(*pDbStatement)->__stmtType = DB_STATEMENT_TYPE_SELECT;
606 _DbStatementImpl::GetInstance(*pDbStatement)->__stmtType = DB_STATEMENT_TYPE_OTHER;
610 return pDbStatement.release();
618 _DatabaseImpl::ExecuteStatementN(const DbStatement& statement)
620 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
621 SysTryReturn(NID_IO, _DbStatementImpl::GetInstance(statement)->__pStmt != null, null, E_INVALID_ARG,
622 "[E_INVALID_ARG] Invalid DbStatement was passed.(null handle was assigned)");
625 DbEnumerator* pDbEnum = null;
626 result r = E_SUCCESS;
628 ret = sqlite3_reset((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
629 if (ret != SQLITE_OK)
631 if (!_AppInfo::IsOspCompat())
633 r = __ConvertNativeSqliteErrorToDetailResult(ret);
637 case E_ILLEGAL_ACCESS:
639 case E_INVALID_FORMAT:
641 case E_INVALID_OPERATION:
649 r = __ConvertNativeSqliteErrorToResult(ret);
652 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
653 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
658 ret = sqlite3_step((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
663 ret = sqlite3_reset((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
664 if (ret != SQLITE_OK)
666 if (!_AppInfo::IsOspCompat())
668 r = __ConvertNativeSqliteErrorToDetailResult(ret);
672 case E_ILLEGAL_ACCESS:
674 case E_INVALID_FORMAT:
676 case E_INVALID_OPERATION:
684 r = __ConvertNativeSqliteErrorToResult(ret);
687 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
688 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
694 if (_DbStatementImpl::GetInstance(statement)->__stmtType == DB_STATEMENT_TYPE_SELECT)
696 unique_ptr<DbEnumerator> pTempDbEnum(_DbEnumeratorImpl::CreateDbEnumeratorInstanceN());
698 SysTryReturn(NID_IO, pTempDbEnum != null, null, E_OUT_OF_MEMORY,
699 "[E_OUT_OF_MEMORY] The memory is insufficient.");
701 _DbEnumeratorImpl::GetInstance(*pTempDbEnum)->__pEnum = _DbStatementImpl::GetInstance(statement)->__pStmt;
702 _DbEnumeratorImpl::GetInstance(*pTempDbEnum)->__pDatabase = _DbStatementImpl::GetInstance(statement)->__pDatabase;
705 ret = sqlite3_reset((sqlite3_stmt*) _DbStatementImpl::GetInstance(statement)->__pStmt);
706 if (ret != SQLITE_OK)
708 if (!_AppInfo::IsOspCompat())
710 r = __ConvertNativeSqliteErrorToDetailResult(ret);
714 case E_ILLEGAL_ACCESS:
716 case E_INVALID_FORMAT:
718 case E_INVALID_OPERATION:
726 r = __ConvertNativeSqliteErrorToResult(ret);
729 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
730 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
735 pDbEnum = pTempDbEnum.release();
740 goto REDO_SQLITE_STEP;
745 if (!_AppInfo::IsOspCompat())
747 r = __ConvertNativeSqliteErrorToDetailResult(ret);
750 case E_ILLEGAL_ACCESS:
751 case E_INVALID_OPERATION:
759 r = __ConvertNativeSqliteErrorToResult(ret);
762 SysLog(NID_IO, "[%s] Failed to execute SQL statement. (%d, %s).", GetErrorMessage(r), ret,
763 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
767 SetLastResult(E_SUCCESS);
776 _DatabaseImpl::ExecuteSql(const String& sql, bool autoCommit)
778 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
781 char* pSqlStr = null;
782 result r = E_SUCCESS;
784 unique_ptr<char[]> pUnTrimStatement(_StringConverter::CopyToCharArrayN(sql));
785 if (pUnTrimStatement == null)
791 // trim leading spaces
792 pSqlStr = pUnTrimStatement.get();
793 while ((*pSqlStr == ' ') || (*pSqlStr == '\t'))
798 if (strncasecmp(pSqlStr, "select", 6) == 0)
800 r = E_INVALID_OPERATION;
804 ret = sqlite3_exec((sqlite3*) __pDatabase, pSqlStr, null, null, null);
805 if (ret != SQLITE_OK)
807 if (!_AppInfo::IsOspCompat())
809 r = __ConvertNativeSqliteErrorToDetailResult(ret);
812 case E_ILLEGAL_ACCESS:
813 case E_INVALID_OPERATION:
821 r = __ConvertNativeSqliteErrorToResult(ret);
824 SysLog(NID_IO, "[%s] Failed to execute SQL statement. (%d, %s).", GetErrorMessage(r), ret,
825 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
836 _DatabaseImpl::QueryN(const String& query)
838 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
842 sqlite3_stmt* pSqlStmt = null;
843 unique_ptr<DbEnumerator> pDbEnum(null);
844 result r = E_SUCCESS;
846 unique_ptr<char[]> pUnTrimStatement(_StringConverter::CopyToCharArrayN(query));
847 if (pUnTrimStatement == null)
853 // trim leading spaces
854 pQuery = pUnTrimStatement.get();
855 while ((*pQuery == ' ') || (*pQuery == '\t'))
860 if (strncasecmp(pQuery, "select", 6) != 0)
862 r = E_INVALID_OPERATION;
866 // prepare the sql statement
867 ret = sqlite3_prepare_v2((sqlite3*) __pDatabase, pQuery, strlen(pQuery), &pSqlStmt, null);
868 if (ret != SQLITE_OK)
870 if (!_AppInfo::IsOspCompat())
872 r = __ConvertNativeSqliteErrorToDetailResult(ret);
875 case E_ILLEGAL_ACCESS:
877 case E_INVALID_FORMAT:
879 case E_INVALID_OPERATION:
887 r = __ConvertNativeSqliteErrorToResult(ret);
890 SysLog(NID_IO, "[%s] Failed to prepare SQL statement (%s). (%d, %s).", GetErrorMessage(r), pQuery,
891 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
895 // ret = sqlite3_reset((sqlite3_stmt *) pSqlStmt);
896 // if (ret != SQLITE_OK)
898 // r = __ConvertNativeSqliteErrorToResult(ret);
899 // SysLog(NID_IO, "[_DatabaseImpl] ERROR: [%s] Failed to reset SQL statement.", GetErrorMessage(r));
903 ret = sqlite3_step(pSqlStmt);
911 pDbEnum.reset(_DbEnumeratorImpl::CreateDbEnumeratorInstanceN());
913 SysTryCatch(NID_IO, pDbEnum != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
914 "[E_OUT_OF_MEMORY] The memory is insufficient.");
916 _DbEnumeratorImpl::GetInstance(*pDbEnum)->__pEnum = pSqlStmt;
917 _DbEnumeratorImpl::GetInstance(*pDbEnum)->__pDatabase = __pDatabase;
918 _DbEnumeratorImpl::GetInstance(*pDbEnum)->__shouldReleaseResource = true;
920 // doing a reset again, so that enumerator first MoveNext() give the first row.
921 ret = sqlite3_reset((sqlite3_stmt*) pSqlStmt);
922 if (ret != SQLITE_OK)
924 if (!_AppInfo::IsOspCompat())
926 r = __ConvertNativeSqliteErrorToDetailResult(ret);
930 case E_ILLEGAL_ACCESS:
932 case E_INVALID_FORMAT:
934 case E_INVALID_OPERATION:
942 r = __ConvertNativeSqliteErrorToResult(ret);
945 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
946 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
952 if (!_AppInfo::IsOspCompat())
954 r = __ConvertNativeSqliteErrorToDetailResult(ret);
957 case E_ILLEGAL_ACCESS:
959 case E_INVALID_OPERATION:
967 r = __ConvertNativeSqliteErrorToResult(ret);
970 SysLog(NID_IO, "[%s] Failed to exectue SQL statement (%s). (%d, %s).", GetErrorMessage(r), pQuery,
971 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
976 return pDbEnum.release();
979 sqlite3_finalize(pSqlStmt);
985 _DatabaseImpl::BeginTransaction(void)
987 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
988 SysTryReturnResult(NID_IO, __transactionGoingOn == false, E_INVALID_STATE,
989 "A transaction is already in progress.");
991 result r = E_SUCCESS;
993 if (sqlite3_get_autocommit((sqlite3*) __pDatabase) == 0)
995 SysLog(NID_IO, "[E_INVALID_STATE] Already in transaction mode.");
996 return E_INVALID_STATE;
999 int ret = sqlite3_exec((sqlite3*) __pDatabase, "BEGIN", null, null, null);
1000 if (ret != SQLITE_OK)
1002 if (!_AppInfo::IsOspCompat())
1004 r = __ConvertNativeSqliteErrorToDetailResult(ret);
1008 case E_ILLEGAL_ACCESS:
1009 case E_OBJECT_LOCKED:
1011 case E_INVALID_FORMAT:
1012 case E_STORAGE_FULL:
1013 case E_INVALID_OPERATION:
1020 r = __ConvertNativeSqliteErrorToResult(ret);
1023 SysLog(NID_IO, "[%s] Failed to begin transaction. (%d, %s)", GetErrorMessage(r), ret,
1024 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
1028 __transactionGoingOn = true;
1035 _DatabaseImpl::CommitTransaction(void)
1037 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1038 SysTryReturnResult(NID_IO, __transactionGoingOn == true, E_INVALID_STATE,
1039 "A transaction is already in progress.");
1042 result r = E_SUCCESS;
1044 if (sqlite3_get_autocommit((sqlite3*) __pDatabase) != 0)
1046 SysLog(NID_IO, "[E_INVALID_STATE] ERROR Message: Not in transaction mode.");
1047 return E_INVALID_STATE;
1050 ret = sqlite3_exec((sqlite3*) __pDatabase, "COMMIT", null, null, null);
1051 if (ret != SQLITE_OK)
1053 if (!_AppInfo::IsOspCompat())
1055 r = __ConvertNativeSqliteErrorToDetailResult(ret);
1059 case E_ILLEGAL_ACCESS:
1060 case E_INVALID_OPERATION:
1067 r = __ConvertNativeSqliteErrorToResult(ret);
1070 SysLog(NID_IO, "[%s] Failed to commit transaction. (%d, %s)", GetErrorMessage(r), ret,
1071 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
1075 __transactionGoingOn = false;
1082 _DatabaseImpl::RollbackTransaction(void)
1084 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1085 SysTryReturnResult(NID_IO, __transactionGoingOn == true, E_INVALID_STATE,
1086 "No transaction in progress.");
1089 result r = E_SUCCESS;
1091 if (sqlite3_get_autocommit((sqlite3*) __pDatabase) != 0)
1093 SysLog(NID_IO, "[E_SUCCESS] No transaction in progress.");
1094 //return E_INVALID_STATE;
1098 ret = sqlite3_exec((sqlite3*) __pDatabase, "ROLLBACK", null, null, null);
1099 if (ret != SQLITE_OK)
1101 if (!_AppInfo::IsOspCompat())
1103 r = __ConvertNativeSqliteErrorToDetailResult(ret);
1107 case E_ILLEGAL_ACCESS:
1108 case E_INVALID_OPERATION:
1115 r = __ConvertNativeSqliteErrorToResult(ret);
1118 SysLog(NID_IO, "[%s] Failed to rollback the transaction. (%d, %s)", GetErrorMessage(r), ret,
1119 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
1123 __transactionGoingOn = false;
1130 _DatabaseImpl::GetName(void) const
1132 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1134 SetLastResult(E_SUCCESS);
1139 _DatabaseImpl::RegisterUserFunction(const String& functionName, const int argumentCount, void* pUserData,
1140 _IDbUserFunctionListener* pUserFunctionListener,
1141 _IDbUserAggregateListener* pUserAggregateListener)
1143 result r = E_SUCCESS;
1144 int sqliteEncoding = 0;
1147 unique_ptr<_DbContextImpl> pDbContext(null);
1148 _DbContextImpl* pTempDbContext = null;
1149 bool entryFound = false;
1152 // Validate input parameters
1153 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1154 SysTryReturnResult(NID_IO, functionName.GetLength() > 0, E_INVALID_ARG,
1155 "Invalid funcName length.");
1156 SysTryReturnResult(NID_IO, argumentCount >= 0 && argumentCount <= MAX_FUNCTION_ARGUMENT_COUNT, E_INVALID_ARG,
1157 "argumentCount < 0 or > 127.");
1159 if (pUserFunctionListener != null && pUserAggregateListener != null)
1161 SysTryReturnResult(NID_IO, 0, E_INVALID_ARG,
1162 "FunctionListener and AggregateListener cannot be registered together");
1165 //select the equivalent sqlite encoding.
1167 unique_ptr<ByteBuffer> pFuncNameBuf(StringUtil::StringToUtf8N(functionName));
1168 SysTryReturn(NID_IO, pFuncNameBuf != null, GetLastResult(),
1169 GetLastResult(), "[%s] Invalid Function name.", GetErrorMessage(GetLastResult()));
1171 utf8len = pFuncNameBuf->GetLimit();
1172 SysTryReturnResult(NID_IO, utf8len > 0 && utf8len <= MAX_UTF8_BYTES, E_INVALID_ARG,
1173 "functionName length in utf8 bytes should be >0 && <=255.");
1175 sqliteEncoding = SQLITE_UTF8; // support only UTF8
1177 //check if the (FunctionName, argumentCount) already exist in the list
1178 for (i = 0; i < __userFunctionContextList.GetCount(); i++)
1180 pTempDbContext = dynamic_cast<_DbContextImpl*> (__userFunctionContextList.GetAt(i));
1181 SysTryReturnResult(NID_IO, pTempDbContext, E_IO, "The __userFunctionContextList has an invalid element.");
1182 if ((pTempDbContext->__argumentCount == argumentCount) &&
1183 (pTempDbContext->__functionName == functionName))
1190 if (entryFound && (null != pUserFunctionListener || null != pUserAggregateListener))
1192 SysTryReturnResult(NID_IO, 0, E_INVALID_ARG,
1193 "(functionName, argumentCount) already registered");
1196 if (pUserFunctionListener != null) // register FunctionListener
1198 pDbContext.reset(new (std::nothrow) _DbContextImpl());
1199 SysTryReturnResult(NID_IO, pDbContext != null, E_OUT_OF_MEMORY,
1200 "The memory is insufficient.");
1202 ret = sqlite3_create_function((sqlite3*) __pDatabase,
1203 (const char*) pFuncNameBuf->GetPointer(), argumentCount, sqliteEncoding, pDbContext.get(),
1204 _DatabaseImpl::UserFunctionListener, null, null);
1206 else if (pUserAggregateListener != null) // register both FunctionStepListener and FunctionFinalListener
1208 pDbContext.reset(new (std::nothrow) _DbContextImpl());
1210 SysTryReturnResult(NID_IO, pDbContext != null, E_OUT_OF_MEMORY,
1211 "The memory is insufficient.");
1213 ret = sqlite3_create_function((sqlite3*) __pDatabase,
1214 (const char*) pFuncNameBuf->GetPointer(), argumentCount, sqliteEncoding, pDbContext.get(),
1215 null, _DatabaseImpl::UserFunctionStepListener, _DatabaseImpl::UserFunctionFinalListener);
1217 else // Delete registered user function/Aggregate
1219 ret = sqlite3_create_function((sqlite3*) __pDatabase,
1220 (const char*) pFuncNameBuf->GetPointer(), argumentCount, sqliteEncoding, null, null, null, null);
1223 if (ret != SQLITE_OK) //error
1225 r = __ConvertNativeSqliteErrorToResult(ret);
1226 SysLog(NID_IO, "[%s] ERROR Message: [%s], Failed to create/delete user defined SQL function.", GetErrorMessage(r),
1227 sqlite3_errmsg((sqlite3*)__pDatabase));
1231 if (entryFound && (!pUserFunctionListener && !pUserAggregateListener)) // delete the user function entry from list
1233 r = __userFunctionContextList.Remove(*pTempDbContext, true);
1234 SysTryReturn(NID_IO, !IsFailed(r), GetLastResult(),
1235 GetLastResult(), "[%s] Failed to remove user function context to the list.", GetErrorMessage(GetLastResult()));
1238 if (pDbContext != null)
1240 //store listener and user data
1241 pDbContext->__pUserData = pUserData;
1242 pDbContext->__argumentCount = argumentCount;
1243 pDbContext->__functionName = functionName;
1244 if (pUserFunctionListener != null)
1246 pDbContext->__pUserFunctionListener = pUserFunctionListener;
1248 if (pUserAggregateListener != null)
1250 pDbContext->__pUserAggregateListener = pUserAggregateListener;
1253 // add entry to the list
1254 r = __userFunctionContextList.Add(*(pDbContext.release()));
1255 SysTryReturn(NID_IO, !IsFailed(r), GetLastResult(),
1256 GetLastResult(), "[%s] Failed to add user function context to the list.", GetErrorMessage(GetLastResult()));
1263 _DatabaseImpl::RegisterUserCollation(const String& collationName, void* pUserData,
1264 _IDbUserCollationListener* pUserCollationListener)
1266 result r = E_SUCCESS;
1267 int sqliteEncoding = 0;
1270 unique_ptr<_DbContextImpl> pDbContext(null);
1271 _DbContextImpl* pTempDbContext = null;
1272 bool entryFound = false;
1275 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1276 SysTryReturnResult(NID_IO, collationName.GetLength() > 0, E_INVALID_ARG,
1277 "Invalid collationName length.");
1279 sqliteEncoding = SQLITE_UTF8; // support only UTF8
1281 unique_ptr<ByteBuffer> pColNameBuf(StringUtil::StringToUtf8N(collationName));
1282 SysTryReturn(NID_IO, pColNameBuf != null, GetLastResult(), GetLastResult(), "[%s] Invalid Function name.",
1283 GetErrorMessage(GetLastResult()));
1285 utf8len = pColNameBuf->GetLimit(); // get UTF_8 bytes length
1286 SysTryReturnResult(NID_IO, utf8len > 0 && utf8len <= MAX_UTF8_BYTES, E_INVALID_ARG,
1287 "functionName length in utf8 bytes should be >0 && <=255.");
1289 //check if the (FunctionName) already registered
1290 for (i = 0; i < __userCollationContextList.GetCount(); i++)
1292 pTempDbContext = dynamic_cast< _DbContextImpl* >(__userCollationContextList.GetAt(i));
1293 SysTryReturnResult(NID_IO, pTempDbContext, E_IO, "The __userCollationContextList has an invalid element.");
1294 if (pTempDbContext->__collationName == collationName)
1301 if (entryFound && (pUserCollationListener != null)) // check if the operation is to delete the user function
1303 SysTryReturnResult(NID_IO, 0, E_INVALID_ARG, "(collationName) already registered");
1306 if (pUserCollationListener != null)
1308 pDbContext.reset(new (std::nothrow) _DbContextImpl());
1309 SysTryReturnResult(NID_IO, pDbContext != null, E_OUT_OF_MEMORY,
1310 "The memory is insufficient.");
1312 // register CollationListener()
1313 ret = sqlite3_create_collation((sqlite3*) __pDatabase, (const char*) pColNameBuf->GetPointer(), sqliteEncoding, pDbContext.get(),
1314 _DatabaseImpl::UserCollationListener);
1316 else // delete Collating function
1318 ret = sqlite3_create_collation((sqlite3*) __pDatabase, (const char*) pColNameBuf->GetPointer(), sqliteEncoding, null, null);
1321 if (ret != SQLITE_OK)
1323 r = __ConvertNativeSqliteErrorToResult(ret);
1324 SysLog(NID_IO, "[%s] ERROR Message: [%s], Failed to create/delete user defined SQL Collation.", GetErrorMessage(r),
1325 sqlite3_errmsg((sqlite3*)__pDatabase));
1329 if (entryFound && !pUserCollationListener) // delete the user collation entry from list
1331 r = __userCollationContextList.Remove(*pTempDbContext, true);
1332 SysTryReturn(NID_IO, !IsFailed(r), GetLastResult(),
1333 GetLastResult(), "[%s] Failed to remove user collation context from the list.", GetErrorMessage(GetLastResult()));
1336 if (pDbContext != null)
1338 //store listener and user data
1339 pDbContext->__pUserData = pUserData;
1340 pDbContext->__collationName = collationName;
1341 pDbContext->__pUserCollationListener = pUserCollationListener;
1342 // add entry to the list
1343 r = __userCollationContextList.Add((*(pDbContext.release())));
1344 SysTryReturn(NID_IO, !IsFailed(r), GetLastResult(),
1345 GetLastResult(), "[%s] Failed to add user collation context to the list.", GetErrorMessage(GetLastResult()));
1353 _DatabaseImpl::GetLastInsertRowId(void) const
1355 SysAssertf(__pDatabase != null, "Not yet constructed. Construct() should be called before use.\n");
1357 // Retrieve last inserted row Id of the specified Db connection.
1358 // sqlite rowIds starts from 1 to max. 0 means no rows available in the database.
1359 // even if we delete the last inserted row, it still returns the rowid of last insert.
1360 // and does not care about any deletions happened.
1361 long long insertRowId = sqlite3_last_insert_rowid(static_cast< sqlite3* >(__pDatabase));
1362 if (insertRowId == 0)
1373 _DatabaseImpl::Delete(const String& databasePath)
1375 result r = E_SUCCESS;
1378 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(databasePath, _AppInfo::IsOspCompat()) == true,
1379 E_INVALID_ARG, " [%ls] is not compatible.", databasePath.GetPointer());
1381 unique_ptr<char[]> pDbPath(_StringConverter::CopyToCharArrayN(databasePath));
1382 if (pDbPath == null)
1384 return GetLastResult();
1388 ret = unlink(pDbPath.get());
1391 r = __ConvertNativeErrorToResult(errno);
1398 _DatabaseImpl::Exists(const String& databasePath)
1400 return _FileImpl::IsFileExist(databasePath);
1404 _DatabaseImpl::UserFunctionListener(sqlite3_context* pContext, int argumentCount, sqlite3_value** pArgList)
1406 _DbContextImpl* pDbContext = null;
1408 pDbContext = static_cast< _DbContextImpl* >(sqlite3_user_data(pContext));
1410 SysTryReturnVoidResult(NID_IO, pDbContext, E_INVALID_STATE, "[E_INVALID_STATE] pDbContext is null.");
1411 SysTryReturnVoidResult(NID_IO, pDbContext->__pUserFunctionListener, E_INVALID_STATE,
1412 "[E_INVALID_STATE] UserAggregateListener is null.");
1414 //Set DbContext data
1415 if (pDbContext->__pContext != (void*) pContext)
1417 pDbContext->__pContext = (void*) pContext;
1420 if (pDbContext->__argumentCount != argumentCount)
1422 SysLog(NID_IO, "Message: __argumentCount mismatch.");
1423 pDbContext->__argumentCount = argumentCount;
1426 if (pDbContext->__pArgList != (void**) pArgList)
1428 pDbContext->__pArgList = (void**) pArgList;
1430 // Invoke the user listener method
1431 pDbContext->__pUserFunctionListener->OnDbUserFunction(*pDbContext, argumentCount);
1433 SetLastResult(E_SUCCESS);
1437 _DatabaseImpl::UserFunctionStepListener(sqlite3_context* pContext, int argumentCount, sqlite3_value** pArgList)
1439 _DbContextImpl* pDbContext = null;
1441 pDbContext = static_cast< _DbContextImpl* >(sqlite3_user_data(pContext));
1443 SysTryReturnVoidResult(NID_IO, pDbContext, E_INVALID_STATE, "[E_INVALID_STATE] pDbContext is null.");
1444 SysTryReturnVoidResult(NID_IO, pDbContext->__pUserAggregateListener, E_INVALID_STATE,
1445 "[E_INVALID_STATE] __pDbContextImpl->__pUserAggregateListener is null.");
1447 //Set DbContext data
1448 if (pDbContext->__pContext != (void*) pContext)
1450 pDbContext->__pContext = (void*) pContext;
1453 if (pDbContext->__argumentCount != argumentCount)
1455 pDbContext->__argumentCount = argumentCount;
1458 if (pDbContext->__pArgList != (void**) pArgList)
1460 pDbContext->__pArgList = (void**) pArgList;
1463 // invoke the user listener method
1464 pDbContext->__pUserAggregateListener->OnDbUserAggregateStep(*pDbContext, argumentCount);
1466 SetLastResult(E_SUCCESS);
1470 _DatabaseImpl::UserFunctionFinalListener(sqlite3_context* pContext)
1472 _DbContextImpl* pDbContext = null;
1474 pDbContext = static_cast< _DbContextImpl* >(sqlite3_user_data(pContext));
1476 SysTryReturnVoidResult(NID_IO, pDbContext, E_INVALID_STATE, "[E_INVALID_STATE] pDbContext is null.");
1477 SysTryReturnVoidResult(NID_IO, pDbContext->__pUserAggregateListener, E_INVALID_STATE,
1478 "[E_INVALID_STATE] UserAggregateListener is null.");
1480 // set context and user data
1481 if (pDbContext->__pContext != (void*) pContext)
1483 pDbContext->__pContext = (void*) pContext;
1486 // invoke the user listener method
1487 pDbContext->__pUserAggregateListener->OnDbUserAggregateFinal(*pDbContext);
1489 SetLastResult(E_SUCCESS);
1493 _DatabaseImpl::UserCollationListener(void* pUserData, int length1, const void* pInput1, int length2, const void* pInput2)
1495 _DbContextImpl* pDbContext = null;
1496 char* pDataInput = null;
1500 pDbContext = static_cast< _DbContextImpl* >(pUserData);
1502 SysTryReturn(NID_IO, pDbContext, 0, E_INVALID_STATE, "[E_INVALID_STATE] pDbContext is null.");
1503 SysTryReturn(NID_IO, pDbContext->__pUserCollationListener, 0, E_INVALID_STATE,
1504 "[E_INVALID_STATE] UserCollationListener is null.");
1506 if (length1 > 0 && (const char*) pInput1 != null)
1508 pDataInput = (char*) malloc((length1 + 1) * sizeof(char));
1510 if (pDataInput == null)
1515 memset(pDataInput, 0, length1 + 1);
1516 strncpy(pDataInput, (const char*) pInput1, length1);
1518 string1.Append((const char*) pDataInput);
1522 if (length2 > 0 && (const char*) pInput2 != null)
1524 pDataInput = (char*) malloc((length2 + 1) * sizeof(char));
1526 if (pDataInput == null)
1531 memset(pDataInput, 0, length2 + 1);
1532 strncpy(pDataInput, (const char*) pInput2, length2);
1534 string2.Append((const char*) pDataInput);
1538 SetLastResult(E_SUCCESS);
1540 return pDbContext->__pUserCollationListener->OnDbUserCollation(string1, string2, pUserData);
1544 _DatabaseImpl::ConvertToSecureDatabase(const String& plainDbPath, const String& secureDbPath, const ByteBuffer* pKey)
1546 result r = E_SUCCESS;
1548 String parentDirPath;
1549 FileAttributes attr;
1551 if (Database::Exists(secureDbPath))
1553 if (GetLastResult() == E_SUCCESS)
1555 r = File::GetAttributes(secureDbPath, attr);
1558 if (attr.IsDirectory())
1560 return E_INVALID_ARG;
1564 return E_FILE_ALREADY_EXIST;
1578 unique_ptr<Database>pDatabase(new (std::nothrow) Database());
1579 SysTryReturnResult(NID_IO, pDatabase, E_OUT_OF_MEMORY, "The memory is insufficient.");
1581 r = pDatabase->Construct(secureDbPath, "a+");
1582 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1584 pDatabase.reset(new (std::nothrow) Database());
1585 SysTryReturnResult(NID_IO, pDatabase, E_OUT_OF_MEMORY, "The memory is insufficient.");
1587 r = pDatabase->Construct(plainDbPath, "r+");
1588 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1590 unique_ptr<String> pSqlStr(new (std::nothrow) String(MAX_DATABASE_SQL_LENGTH));
1591 SysTryReturnResult(NID_IO, pSqlStr != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1593 unique_ptr<char[]> pPhysicalDbPath(_StringConverter::CopyToCharArrayN(secureDbPath));
1594 SysTryReturn(NID_IO, pPhysicalDbPath != null, GetLastResult(), GetLastResult(), "[%s] Invalid file path.", GetErrorMessage(GetLastResult()));
1596 unique_ptr<byte[]> pDbKey(_SecureIoUtil::GenerateDatabaseKeyN(pKey));
1597 SysTryReturnResult(NID_IO, pDbKey != null, E_INVALID_ARG, "GenerateDatabaseKeyN returned null.");
1599 pSqlStr->Format(MAX_DATABASE_SQL_LENGTH, L"ATTACH DATABASE '%s' AS encrypted KEY '%s'", pPhysicalDbPath.get(), pDbKey.get());
1601 sql.Append(*pSqlStr);
1602 r = pDatabase->ExecuteSql(sql, true);
1603 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1606 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"));
1607 r = GetLastResult();
1613 String tempQuery(L"encrypted.");
1615 while (pEnum->MoveNext() == E_SUCCESS)
1617 r = pEnum->GetStringAt(0, schema);
1620 if (r == E_INVALID_STATE || r == E_TYPE_MISMATCH || r == E_INVALID_ENCODING_RANGE) //internal exception by this method
1627 if (schema.StartsWith(L"sqlite_", MAX_SQLCIPHER_SCHEMA_PREFIX_SIZE))
1632 r = schema.Insert(tempQuery, MAX_SQLCIPHER_SCHEMA_PREFIX_SIZE);
1638 r = pDatabase->ExecuteSql(schema, true);
1639 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to caller...", GetErrorMessage(r));
1645 SysPropagate(NID_IO, r);
1649 pEnum.reset(pDatabase->QueryN(L"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"));
1650 r = GetLastResult();
1656 while (pEnum->MoveNext() == E_SUCCESS)
1658 r = pEnum->GetStringAt(0, tableName);
1661 if (r == E_INVALID_STATE || r == E_TYPE_MISMATCH || r == E_INVALID_ENCODING_RANGE) //internal exception by this method
1669 if (tableName.StartsWith(L"sqlite_", 0))
1674 pSqlStr.reset(new (std::nothrow) String(MAX_DATABASE_SQL_LENGTH));
1675 SysTryReturnResult(NID_IO, pSqlStr, E_OUT_OF_MEMORY, "The memory is insufficient.");
1677 pSqlStr->Format(MAX_DATABASE_SQL_LENGTH, L"INSERT INTO encrypted.%ls SELECT * FROM %ls", tableName.GetPointer(), tableName.GetPointer());
1679 sql.Append(*pSqlStr);
1680 r = pDatabase->ExecuteSql(sql, true);
1681 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1688 SysPropagate(NID_IO, r);
1692 sql.Append(L"DETACH DATABASE encrypted");
1694 r = pDatabase->ExecuteSql(sql, true);
1695 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagating to the caller...", GetErrorMessage(r));
1701 _DatabaseImpl::GetInstance(Database& database)
1703 return database.__pDatabaseImpl;
1706 const _DatabaseImpl*
1707 _DatabaseImpl::GetInstance(const Database& database)
1709 return database.__pDatabaseImpl;