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_DbEnumeratorImpl.cpp
20 * @brief This is the implementation file for _DbEnumeratorImpl class.
24 #include <semaphore.h>
26 #include <unique_ptr.h>
29 #include <FBaseInteger.h>
30 #include <FBaseDouble.h>
31 #include <FBaseString.h>
32 #include <FBaseByteBuffer.h>
33 #include <FBaseDateTime.h>
34 #include <FBaseUtilStringUtil.h>
35 #include <FBaseColLinkedList.h>
36 #include <FBaseColArrayList.h>
37 #include <FBaseColIEnumerator.h>
38 #include <FBaseSysLog.h>
40 #include <FBase_NativeError.h>
41 #include <FApp_AppInfo.h>
42 #include <FSys_RuntimeInfoImpl.h>
43 #include <FIo_DbEnumeratorImpl.h>
46 using namespace Tizen::Base;
47 using namespace Tizen::Base::Utility;
48 using namespace Tizen::Base::Runtime;
49 using namespace Tizen::System;
50 using namespace Tizen::App;
51 using namespace Tizen::Base::Collection;
53 namespace Tizen { namespace Io
55 static const unsigned int _MAX_DB_CACHE_SIZE = 2 * 1024 * 1024; // default cache size is 2MB
63 LinkedList dbValuesList;
76 if (this->hasData == true)
78 dbValuesList.RemoveAll(true);
90 unique_ptr<char[]> pData;
93 _DbColumn::_DbColumn(void)
100 _DbColumn::~_DbColumn(void)
104 class _DbEnumeratorCache
109 * This is the default constructor for this class.
111 _DbEnumeratorCache(void);
112 ~_DbEnumeratorCache(void);
114 unsigned int __currentUsedMemory;
115 _DbRow* __pCurrentDbRow;
116 LinkedList __dbColumnNameList;
117 LinkedList __dbRowList;
119 friend class _DbEnumeratorImpl;
123 _DbEnumeratorCache::_DbEnumeratorCache(void)
124 : __currentUsedMemory(0)
125 , __pCurrentDbRow(null)
129 _DbEnumeratorCache::~_DbEnumeratorCache(void)
131 __dbColumnNameList.RemoveAll(true);
132 __dbRowList.RemoveAll(true);
135 _DbEnumeratorImpl::_DbEnumeratorImpl(void)
136 : __shouldReleaseResource(false)
141 , __currentRowIndex(-1)
142 , __pDbEnumeratorCache(null)
146 _DbEnumeratorImpl::~_DbEnumeratorImpl(void)
148 result r = E_SUCCESS;
151 if (__shouldReleaseResource && __pEnum)
153 ret = sqlite3_finalize(static_cast <sqlite3_stmt*>(__pEnum));
154 if (ret != SQLITE_OK)
156 r = __ConvertNativeSqliteErrorToResult(ret);
157 SysLog(NID_IO, "[%s] Failed to finalize SQL statement (%d, %s).", GetErrorMessage(
158 r), ret, sqlite3_errmsg((sqlite3*) __pDatabase));
162 delete __pDbEnumeratorCache;
166 _DbEnumeratorImpl::CacheRow(bool cacheColumnNamesToo)
168 SysTryReturnResult(NID_IO, __pEnum != null, E_INVALID_STATE,
169 "The Object is not constructed or the database is already been closed.");
170 SysTryReturnResult(NID_IO, __pDbEnumeratorCache != null, E_INVALID_STATE,
171 "The Object is not constructed or the database is already been closed.");
174 result r = E_SUCCESS;
176 // check if all the rows are been cached already
179 SysTryReturnResult(NID_IO, __currentRowIndex < (__rowCount - 1), E_OUT_OF_RANGE,
180 "Reached to the end of the result set.");
183 ret = sqlite3_step((sqlite3_stmt*) __pEnum);
188 // set max rows in the result set
189 if (__currentRowIndex >= 0)
191 __rowCount = __currentRowIndex + 1;
193 return E_OUT_OF_RANGE;
198 unique_ptr<_DbRow> pDbRow(new (std::nothrow) _DbRow);
199 SysTryReturnResult(NID_IO, pDbRow != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
201 for (int i = 0; i < __columnCount; i++)
203 // prepare column name list only once
204 if (cacheColumnNamesToo == true)
207 const char* pName = sqlite3_column_name((sqlite3_stmt*) __pEnum, i);
209 r = __pDbEnumeratorCache->__dbColumnNameList.Add(* new (std::nothrow) String(pName));
210 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
213 unique_ptr<_DbColumn> pDbColumn(new (std::nothrow) _DbColumn);
214 SysTryReturnResult(NID_IO, pDbColumn != null, E_OUT_OF_MEMORY,
215 "The memory is insufficient.");
217 int columnType = sqlite3_column_type((sqlite3_stmt*) __pEnum, i);
219 pDbColumn->type = columnType;
225 int size = sizeof(long long);
226 unique_ptr<char[]> pData(new (std::nothrow) char[size + 1]);
227 SysTryReturnResult(NID_IO, pData != null, E_OUT_OF_MEMORY,
228 "The memory is insufficient.");
229 memset(pData.get(), 0, size + 1);
230 long long value = sqlite3_column_int64((sqlite3_stmt*) __pEnum, i);
231 memcpy(pData.get(), &value, size);
232 pDbColumn->size = size;
233 pDbColumn->pData = move(pData);
238 int size = sizeof(double);
239 unique_ptr<char[]> pData(new (std::nothrow) char[size + 1]);
240 SysTryReturnResult(NID_IO, pData != null, E_OUT_OF_MEMORY,
241 "The memory is insufficient.");
242 memset(pData.get(), 0, size + 1);
243 double doubleValue = sqlite3_column_double((sqlite3_stmt*) __pEnum, i);
244 memcpy(pData.get(), &doubleValue, size);
245 pDbColumn->size = size;
246 pDbColumn->pData = move(pData);
251 int size = sqlite3_column_bytes((sqlite3_stmt*) __pEnum, i);
252 unique_ptr<char[]> pData(new (std::nothrow) char[size + 1]);
253 SysTryReturnResult(NID_IO, pData != null, E_OUT_OF_MEMORY,
254 "The memory is insufficient.");
255 memset(pData.get(), 0, size + 1);
256 char* pTextData = (char*) sqlite3_column_text((sqlite3_stmt*) __pEnum, i);
257 memcpy(pData.get(), pTextData, size);
258 pDbColumn->size = size;
259 pDbColumn->pData = move(pData);
264 int size = sqlite3_column_bytes((sqlite3_stmt*) __pEnum, i);
265 unique_ptr<char[]> pData(new (std::nothrow) char[size + 1]);
266 SysTryReturnResult(NID_IO, pData != null, E_OUT_OF_MEMORY,
267 "The memory is insufficient.");
268 memset(pData.get(), 0, size + 1);
269 char* pBlobData = (char*) sqlite3_column_blob((sqlite3_stmt*) __pEnum, i);
270 memcpy(pData.get(), pBlobData, size);
271 pDbColumn->size = size;
272 pDbColumn->pData = move(pData);
277 int size = sqlite3_column_bytes((sqlite3_stmt*) __pEnum, i);
278 pDbColumn->size = size;
283 SysTryReturnResult(NID_IO, false, E_DATABASE, "The column type is invalid.");
287 dbRowSize += pDbColumn->size;
288 r = pDbRow->dbValuesList.Add(*pDbColumn.release());
289 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
292 __pDbEnumeratorCache->__currentUsedMemory += dbRowSize;
294 if (__pDbEnumeratorCache->__currentUsedMemory > _MAX_DB_CACHE_SIZE)
296 // remove old rows in FIFO manner till there is enough space for the current row.
297 for (int i = 0; i < __pDbEnumeratorCache->__dbRowList.GetCount(); i++)
299 _DbRow* pTmpDbRow = dynamic_cast< _DbRow* >(__pDbEnumeratorCache->__dbRowList.GetAt(i));
300 SysTryReturn(NID_IO, pTmpDbRow != null, GetLastResult(), GetLastResult(), "[%s] Propagated.", GetErrorMessage(GetLastResult()));
301 if (pTmpDbRow->hasData == true)
303 pTmpDbRow->dbValuesList.RemoveAll(true);
304 pTmpDbRow->hasData = false;
305 __pDbEnumeratorCache->__currentUsedMemory -= pTmpDbRow->dataSize;
306 pTmpDbRow->dataSize = 0;
308 if (__pDbEnumeratorCache->__currentUsedMemory <= _MAX_DB_CACHE_SIZE)
316 pDbRow->hasData = true;
317 pDbRow->dataSize = dbRowSize;
318 _DbRow* pTmpDbRow = pDbRow.release();
319 r = __pDbEnumeratorCache->__dbRowList.Add(*pTmpDbRow);
322 pTmpDbRow->dbValuesList.RemoveAll(true);
324 SysLog(NID_IO, "[%s] Propagated.", GetErrorMessage(r));
330 // set current cursor
331 __pDbEnumeratorCache->__pCurrentDbRow = pTmpDbRow;
337 if (!_AppInfo::IsOspCompat())
339 r = __ConvertNativeSqliteErrorToDetailResult(ret);
343 case E_ILLEGAL_ACCESS:
345 case E_INVALID_OPERATION:
353 r = __ConvertNativeSqliteErrorToResult(ret);
356 SysLog(NID_IO, "[%s] Failed to move row index. (%d, %s).", GetErrorMessage(r), ret,
357 sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
367 _DbEnumeratorImpl::CacheRow(_DbRow& dbRow, int rowIndex)
369 result r = E_SUCCESS;
372 SysTryReturnResult(NID_IO, __pEnum != null, E_INVALID_STATE,
373 "The Object is not constructed or the database is already been closed.");
375 SysTryReturnResult(NID_IO, __pDbEnumeratorCache != null, E_INVALID_STATE,
376 "The Object is not constructed or the database is already been closed.");
378 // reset sqlite result set.
379 ret = sqlite3_reset((sqlite3_stmt*) __pEnum);
380 if (ret != SQLITE_OK)
382 if (!_AppInfo::IsOspCompat())
384 r = __ConvertNativeSqliteErrorToDetailResult(ret);
388 case E_ILLEGAL_ACCESS:
390 case E_INVALID_FORMAT:
392 case E_INVALID_OPERATION:
400 r = __ConvertNativeSqliteErrorToResult(ret);
403 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
404 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
408 // move cursor to desired position.
409 for (int i = 0; i <= rowIndex; i++)
411 ret = sqlite3_step((sqlite3_stmt*) __pEnum);
412 if (ret != SQLITE_ROW)
414 SysLog(NID_IO, "Did not yield any result row");
419 // ret == SQLITE_ROW, cache the row.
422 for (int i = 0; i < __columnCount; i++)
424 unique_ptr<_DbColumn> pDbColumn(new (std::nothrow) _DbColumn);
425 SysTryReturnResult(NID_IO, pDbColumn != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
427 int columnType = sqlite3_column_type((sqlite3_stmt*) __pEnum, i);
429 pDbColumn->type = columnType;
435 int size = sizeof(long long);
436 unique_ptr<char[]> pData(new (std::nothrow) char[size + 1]);
437 SysTryReturnResult(NID_IO, pData != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
438 memset(pData.get(), 0, size + 1);
439 long long value = sqlite3_column_int64((sqlite3_stmt*) __pEnum, i);
440 memcpy(pData.get(), &value, size);
441 pDbColumn->size = size;
442 pDbColumn->pData = move(pData);
447 int size = sizeof(double);
448 unique_ptr<char[]> pData(new (std::nothrow) char[size + 1]);
449 SysTryReturnResult(NID_IO, pData != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
450 memset(pData.get(), 0, size + 1);
451 double doubleValue = sqlite3_column_double((sqlite3_stmt*) __pEnum, i);
452 memcpy(pData.get(), &doubleValue, size);
453 pDbColumn->size = size;
454 pDbColumn->pData = move(pData);
459 int size = sqlite3_column_bytes((sqlite3_stmt*) __pEnum, i);
460 unique_ptr<char[]> pData(new (std::nothrow) char[size + 1]);
461 SysTryReturnResult(NID_IO, pData != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
462 memset(pData.get(), 0, size + 1);
463 char* pTextData = (char*) sqlite3_column_text((sqlite3_stmt*) __pEnum, i);
464 memcpy(pData.get(), pTextData, size);
465 pDbColumn->size = size;
466 pDbColumn->pData = move(pData);
471 int size = sqlite3_column_bytes((sqlite3_stmt*) __pEnum, i);
472 unique_ptr<char[]> pData(new (std::nothrow) char[size + 1]);
473 SysTryReturnResult(NID_IO, pData != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
474 memset(pData.get(), 0, size + 1);
475 char* pBlobData = (char*) sqlite3_column_blob((sqlite3_stmt*) __pEnum, i);
476 memcpy(pData.get(), pBlobData, size);
477 pDbColumn->size = size;
478 pDbColumn->pData = move(pData);
483 int size = sqlite3_column_bytes((sqlite3_stmt*) __pEnum, i);
484 pDbColumn->size = size;
489 SysTryReturnResult(NID_IO, false, E_DATABASE, "The column type is invalid.");
494 dbRowSize += pDbColumn->size;
495 r = dbRow.dbValuesList.Add(*pDbColumn.release());
496 SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
499 __pDbEnumeratorCache->__currentUsedMemory += dbRowSize;
501 if (__pDbEnumeratorCache->__currentUsedMemory > _MAX_DB_CACHE_SIZE)
503 // In this case remove old rows in LIFO manner till there is enough space for the current row.
504 for (int i = __pDbEnumeratorCache->__dbRowList.GetCount() - 1; i >= 0; i--)
506 _DbRow* pTmpDbRow = dynamic_cast< _DbRow* >(__pDbEnumeratorCache->__dbRowList.GetAt(i));
507 SysTryCatch(NID_IO, pTmpDbRow != null, r = GetLastResult(), GetLastResult(), "[%s] Propagated.", GetErrorMessage(GetLastResult()));
508 if (pTmpDbRow->hasData == true)
510 pTmpDbRow->dbValuesList.RemoveAll(true);
511 pTmpDbRow->hasData = false;
512 __pDbEnumeratorCache->__currentUsedMemory -= pTmpDbRow->dataSize;
513 pTmpDbRow->dataSize = 0;
515 if (__pDbEnumeratorCache->__currentUsedMemory <= _MAX_DB_CACHE_SIZE)
517 break; // found enough space.
523 dbRow.hasData = true;
524 dbRow.dataSize = dbRowSize;
525 __currentRowIndex = rowIndex;
527 // set current cursor
528 __pDbEnumeratorCache->__pCurrentDbRow = &dbRow;
534 dbRow.dbValuesList.RemoveAll(true);
535 dbRow.hasData = false;
541 _DbEnumeratorImpl::MoveNext(void)
543 SysTryReturnResult(NID_IO, __pEnum != null, E_INVALID_STATE,
544 "The Object is not constructed or the database is already been closed.");
546 _DbRow* pDbRow = null;
547 result r = E_SUCCESS;
549 if (__pDbEnumeratorCache == null) // called for the first time
551 __pDbEnumeratorCache = new (std::nothrow) _DbEnumeratorCache; // allocate only once
552 SysTryReturnResult(NID_IO, __pDbEnumeratorCache != null, E_OUT_OF_MEMORY,
553 "The memory is insufficient.");
555 __columnCount = sqlite3_column_count((sqlite3_stmt*) __pEnum);
557 SysLog(NID_IO, "__columnCount: %d", __columnCount);
559 return this->CacheRow(true);
563 SysLog(NID_IO, "current used memory:%d", __pDbEnumeratorCache->__currentUsedMemory);
564 if ((__currentRowIndex + 1 <= __pDbEnumeratorCache->__dbRowList.GetCount() - 1))
566 pDbRow = dynamic_cast <_DbRow*>(__pDbEnumeratorCache->__dbRowList.GetAt(__currentRowIndex + 1));
567 SysTryReturnResult(NID_IO, pDbRow != null, E_SYSTEM, "The method cannot proceed due to a severe system error.");
569 if (pDbRow->hasData == true)
572 __pDbEnumeratorCache->__pCurrentDbRow = pDbRow;
576 return CacheRow(*pDbRow, __currentRowIndex + 1);
581 return this->CacheRow();
589 _DbEnumeratorImpl::MovePrevious(void)
591 result r = E_SUCCESS;
593 SysTryReturnResult(NID_IO, __pEnum != null, E_INVALID_STATE,
594 "The Object is not constructed or the database is already been closed.");
595 SysTryReturn(NID_IO, __pDbEnumeratorCache != null, E_INVALID_STATE, E_INVALID_STATE,
596 "[E_INVALID_STATE] The method has tried to fetch the column data of a result set that is not activated.");
597 SysTryReturnResult(NID_IO, __currentRowIndex > 0, E_OUT_OF_RANGE,
598 "The Method has reached out of the result set.");
600 // since no restriction on window size, this case should work all the times.
601 __pDbEnumeratorCache->__pCurrentDbRow = dynamic_cast< _DbRow* >(__pDbEnumeratorCache->__dbRowList.GetAt(__currentRowIndex - 1));
603 if (__pDbEnumeratorCache->__pCurrentDbRow)
605 if (__pDbEnumeratorCache->__pCurrentDbRow->hasData == true)
611 return CacheRow(*(__pDbEnumeratorCache->__pCurrentDbRow), __currentRowIndex - 1);
619 _DbEnumeratorImpl::MoveFirst(void)
621 SysTryReturnResult(NID_IO, __pEnum != null, E_INVALID_STATE,
622 "The Object is not constructed or the database is already been closed.");
624 if (__pDbEnumeratorCache == null) // if called for the first time
626 return this->MoveNext();
630 if (__currentRowIndex == 0)
632 return E_SUCCESS; // __pCurrentDbRow cursor is pointing to first row
636 __pDbEnumeratorCache->__pCurrentDbRow = dynamic_cast< _DbRow* >(__pDbEnumeratorCache->__dbRowList.GetAt(0));
637 if (__pDbEnumeratorCache->__pCurrentDbRow)
639 if (__pDbEnumeratorCache->__pCurrentDbRow->hasData == true)
641 __currentRowIndex = 0;
645 return CacheRow(*(__pDbEnumeratorCache->__pCurrentDbRow), 0);
648 else // this should not happen!!
650 // reset and do MoveNext()
651 delete __pDbEnumeratorCache;
652 __pDbEnumeratorCache = null;
653 __currentRowIndex = -1;
656 result r = this->Reset(); // to call sqlite3_reset()
657 SysTryReturnResult(NID_IO, r == E_SUCCESS, r, "Propagated.");
659 return this->MoveNext();
668 _DbEnumeratorImpl::MoveLast(void)
670 result r = E_SUCCESS;
671 _DbRow* pDbRow = null;
673 SysTryReturnResult(NID_IO, __pEnum != null, E_INVALID_STATE,
674 "The Object is not constructed or the database is already been closed.");
676 if (__pDbEnumeratorCache == null) // if called for the first time
679 r = this->MoveNext();
680 SysTryReturnResult(NID_IO, r == E_SUCCESS, r, "Propagated.");
682 // cache all the rows
685 r = this->CacheRow();
686 if (r == E_OUT_OF_RANGE)
695 if (__rowCount > 0 && __currentRowIndex == (__rowCount - 1))
697 return E_SUCCESS; // already @last row.
700 // move cursor from __currentRowIndex + 1 to the end of the row list.
701 for (int i = __currentRowIndex + 1; i < __pDbEnumeratorCache->__dbRowList.GetCount(); i++)
703 // find the missing row index
704 pDbRow = dynamic_cast< _DbRow* >(__pDbEnumeratorCache->__dbRowList.GetAt(i));
707 if (pDbRow->hasData == true)
709 __pDbEnumeratorCache->__pCurrentDbRow = pDbRow;
710 __currentRowIndex = i;
714 r = this->CacheRow(*pDbRow, i);
715 SysTryReturn(NID_IO, !(IsFailed(r)), r, r, "[%s] Propagated.", GetErrorMessage(r));
724 if (__rowCount > 0 && __currentRowIndex == (__rowCount - 1))
726 return E_SUCCESS; // __dbRowList contains all the rows and __currentRowIndex is @last row.
730 // cache remaining rows
733 r = this->CacheRow();
734 if (r == E_OUT_OF_RANGE)
747 _DbEnumeratorImpl::Reset(void)
749 SysTryReturnResult(NID_IO, __pEnum != null, E_INVALID_STATE,
750 "The Object is not constructed or the database is already been closed.");
753 result r = E_SUCCESS;
755 if (__pDbEnumeratorCache != null)
757 // by resetting row offset and current row, can re-use the cache for later purpose.
758 __pDbEnumeratorCache->__pCurrentDbRow = null;
759 __currentRowIndex = -1;
763 ret = sqlite3_reset((sqlite3_stmt*) __pEnum);
764 if (ret != SQLITE_OK)
766 if (!_AppInfo::IsOspCompat())
768 r = __ConvertNativeSqliteErrorToDetailResult(ret);
772 case E_ILLEGAL_ACCESS:
774 case E_INVALID_FORMAT:
776 case E_INVALID_OPERATION:
784 r = __ConvertNativeSqliteErrorToResult(ret);
787 SysLog(NID_IO, "[%s] Failed to reset SQL statement. (%d, %s).", GetErrorMessage(r),
788 ret, sqlite3_errmsg(static_cast< sqlite3* >(__pDatabase)));
796 _DbEnumeratorImpl::GetIntAt(int columnIndex, int& value) const
798 SysTryReturnResult(NID_IO, __pEnum != null, E_INVALID_STATE,
799 "The Object is not constructed or the database is already been closed.");
800 SysTryReturnResult(NID_IO, columnIndex >= 0 && columnIndex < __columnCount, E_INVALID_ARG,
801 "Given column index is out of range.");
802 SysTryReturnResult(NID_IO, __pDbEnumeratorCache != null, E_INVALID_STATE,
803 "The method has tried to fetch the column data of a result set that is not activated.");
804 SysTryReturnResult(NID_IO, __pDbEnumeratorCache->__pCurrentDbRow != null, E_SYSTEM,
805 "Result row is not activated.");
807 _DbColumn* pDbColumn = dynamic_cast < _DbColumn* >(__pDbEnumeratorCache->__pCurrentDbRow->dbValuesList.GetAt(columnIndex));
808 SysTryReturnResult(NID_IO, pDbColumn != null, E_SYSTEM, "The specified column at index %d is not found from the result set.", columnIndex);
810 SysTryReturnResult(NID_IO, pDbColumn->type == SQLITE_INTEGER, E_TYPE_MISMATCH,
811 "Trying to access column of different type.");
813 SysTryReturnResult(NID_IO, pDbColumn->pData != null, E_SYSTEM, "Data for specified column does not exist.");
815 value = *((int *)pDbColumn->pData.get());
821 _DbEnumeratorImpl::GetInt64At(int columnIndex, long long& value) const
823 SysTryReturnResult(NID_IO, __pEnum != null, E_INVALID_STATE,
824 "The Object is not constructed or the database is already been closed.");
825 SysTryReturnResult(NID_IO, columnIndex >= 0 && columnIndex < __columnCount, E_INVALID_ARG,
826 "Given column index is out of range.");
827 SysTryReturnResult(NID_IO, __pDbEnumeratorCache != null, E_INVALID_STATE,
828 "The method has tried to fetch the column data of a result set that is not activated.");
829 SysTryReturnResult(NID_IO, __pDbEnumeratorCache->__pCurrentDbRow != null, E_SYSTEM,
830 "Result row is not activated.");
832 _DbColumn* pDbColumn = dynamic_cast < _DbColumn* >(__pDbEnumeratorCache->__pCurrentDbRow->dbValuesList.GetAt(columnIndex));
833 SysTryReturnResult(NID_IO, pDbColumn != null, E_SYSTEM, "The specified column at index %d is not found from the result set.", columnIndex);
835 SysTryReturnResult(NID_IO, pDbColumn->type == SQLITE_INTEGER, E_TYPE_MISMATCH,
836 "Trying to access column of different type.");
837 SysTryReturnResult(NID_IO, pDbColumn->pData != null, E_SYSTEM, "Data for specified column does not exist.");
839 value = *((long long *)pDbColumn->pData.get());
845 _DbEnumeratorImpl::GetDoubleAt(int columnIndex, double& value) const
847 SysTryReturnResult(NID_IO, __pEnum != null, E_INVALID_STATE,
848 "The Object is not constructed or the database is already been closed.");
849 SysTryReturnResult(NID_IO, columnIndex >= 0 && columnIndex < __columnCount, E_INVALID_ARG,
850 "Given column index is out of range.");
851 SysTryReturnResult(NID_IO, __pDbEnumeratorCache != null, E_INVALID_STATE,
852 "The method has tried to fetch the column data of a result set that is not activated.");
853 SysTryReturnResult(NID_IO, __pDbEnumeratorCache->__pCurrentDbRow != null, E_SYSTEM,
854 "Result row is not activated.");
856 _DbColumn* pDbColumn = dynamic_cast < _DbColumn* >(__pDbEnumeratorCache->__pCurrentDbRow->dbValuesList.GetAt(columnIndex));
857 SysTryReturnResult(NID_IO, pDbColumn != null, E_SYSTEM, "The specified column at index %d is not found from the result set.", columnIndex);
858 SysTryReturnResult(NID_IO, pDbColumn->type == SQLITE_FLOAT, E_TYPE_MISMATCH, "Trying to access column of different type.");
859 SysTryReturnResult(NID_IO, pDbColumn->pData != null, E_SYSTEM, "Data for specified column does not exist.");
861 value = *((double *)pDbColumn->pData.get());
867 _DbEnumeratorImpl::GetStringAt(int columnIndex, String& value) const
869 SysTryReturnResult(NID_IO, __pEnum != null, E_INVALID_STATE,
870 "The Object is not constructed or the database is already been closed.");
871 SysTryReturnResult(NID_IO, columnIndex >= 0 && columnIndex < __columnCount, E_INVALID_ARG,
872 "Given column index is out of range.");
873 SysTryReturnResult(NID_IO, __pDbEnumeratorCache != null, E_INVALID_STATE,
874 "The method has tried to fetch the column data of a result set that is not activated.");
875 SysTryReturnResult(NID_IO, __pDbEnumeratorCache->__pCurrentDbRow != null, E_SYSTEM,
876 "Result row is not activated.");
878 _DbColumn* pDbColumn = dynamic_cast < _DbColumn* >(__pDbEnumeratorCache->__pCurrentDbRow->dbValuesList.GetAt(columnIndex));
879 SysTryReturnResult(NID_IO, pDbColumn != null, E_SYSTEM, "The specified column at index %d is not found from the result set.", columnIndex);
880 SysTryReturnResult(NID_IO, pDbColumn->type == SQLITE_TEXT, E_TYPE_MISMATCH, "Trying to access column of different type.");
881 SysTryReturnResult(NID_IO, pDbColumn->pData != null, E_SYSTEM, "Data for specified column does not exist.");
883 result r = StringUtil::Utf8ToString(const_cast< char* >(pDbColumn->pData.get()), value);
884 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] Propagating to caller...", GetErrorMessage(r));
890 _DbEnumeratorImpl::GetBlobAt(int columnIndex, ByteBuffer& value) const
892 SysTryReturnResult(NID_IO, __pEnum != null, E_INVALID_STATE,
893 "The Object is not constructed or the database is already been closed.");
894 SysTryReturnResult(NID_IO, columnIndex >= 0 && columnIndex < __columnCount, E_INVALID_ARG,
895 "Given column index is out of range.");
896 SysTryReturnResult(NID_IO, __pDbEnumeratorCache != null, E_INVALID_STATE,
897 "The method has tried to fetch the column data of a result set that is not activated.");
898 SysTryReturnResult(NID_IO, __pDbEnumeratorCache->__pCurrentDbRow != null, E_SYSTEM,
899 "Result row is not activated.");
901 _DbColumn* pDbColumn = dynamic_cast < _DbColumn* >(__pDbEnumeratorCache->__pCurrentDbRow->dbValuesList.GetAt(columnIndex));
902 SysTryReturnResult(NID_IO, pDbColumn != null, E_SYSTEM, "The specified column at index %d is not found from the result set.", columnIndex);
903 SysTryReturnResult(NID_IO, pDbColumn->type == SQLITE_BLOB, E_TYPE_MISMATCH, "Trying to access column of different type.");
905 int blobLen = pDbColumn->size;
906 SysTryReturnResult(NID_IO, pDbColumn->pData != null, E_SYSTEM, "Data for specified column does not exist.");
908 const byte* pBlob = reinterpret_cast< const byte* >(pDbColumn->pData.get());
909 result r = value.SetArray(pBlob, 0, blobLen);
910 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] Propagating to caller...", GetErrorMessage(r));
916 _DbEnumeratorImpl::GetBlobAt(int columnIndex, void* buffer, int size) const
918 SysTryReturnResult(NID_IO, __pEnum != null, E_INVALID_STATE,
919 "The Object is not constructed or the database is already been closed.");
920 SysTryReturnResult(NID_IO, columnIndex >= 0 && columnIndex < __columnCount, E_INVALID_ARG,
921 "Given column index is out of range.");
922 SysTryReturnResult(NID_IO, buffer != null, E_INVALID_ARG, "Null pointer was passed.");
923 SysTryReturnResult(NID_IO, size > 0, E_INVALID_ARG, "Invalid size was passed.");
924 SysTryReturnResult(NID_IO, __pDbEnumeratorCache != null, E_INVALID_STATE,
925 "The method has tried to fetch the column data of a result set that is not activated.");
926 SysTryReturnResult(NID_IO, __pDbEnumeratorCache->__pCurrentDbRow != null, E_SYSTEM,
927 "Result row is not activated.");
929 _DbColumn* pDbColumn = dynamic_cast < _DbColumn* >(__pDbEnumeratorCache->__pCurrentDbRow->dbValuesList.GetAt(columnIndex));
930 SysTryReturnResult(NID_IO, pDbColumn != null, E_SYSTEM, "The specified column at index %d is not found from the result set.", columnIndex);
931 SysTryReturnResult(NID_IO, pDbColumn->type == SQLITE_BLOB, E_TYPE_MISMATCH, "Trying to access column of different type.");
933 int blobLen = pDbColumn->size;
934 SysTryReturnResult(NID_IO, pDbColumn->pData != null, E_SYSTEM, "Data for specified column does not exist.");
936 const byte* pBlob = reinterpret_cast< const byte* >(pDbColumn->pData.get());
937 memcpy(buffer, pBlob, (blobLen < size) ? blobLen : size);
948 _DbEnumeratorImpl::GetDateTimeAt(int columnIndex, DateTime& value) const
950 SysTryReturnResult(NID_IO, __pEnum != null, E_INVALID_STATE,
951 "The Object is not constructed or the database is already been closed.");
952 SysTryReturnResult(NID_IO, columnIndex >= 0 && columnIndex < __columnCount, E_INVALID_ARG,
953 "Given column index is out of range.");
954 SysTryReturnResult(NID_IO, __pDbEnumeratorCache != null, E_INVALID_STATE,
955 "The method has tried to fetch the column data of a result set that is not activated.");
956 SysTryReturnResult(NID_IO, __pDbEnumeratorCache->__pCurrentDbRow != null, E_SYSTEM,
957 "Result row is not activated.");
959 _DbColumn* pDbColumn = dynamic_cast < _DbColumn* >(__pDbEnumeratorCache->__pCurrentDbRow->dbValuesList.GetAt(columnIndex));
960 SysTryReturnResult(NID_IO, pDbColumn != null, E_SYSTEM, "The specified column at index %d is not found from the result set.", columnIndex);
961 SysTryReturnResult(NID_IO, pDbColumn->type == SQLITE_TEXT, E_TYPE_MISMATCH, "Trying to access column of different type.");
962 SysTryReturnResult(NID_IO, pDbColumn->pData != null, E_SYSTEM, "Data for specified column does not exist.");
964 const char* pStr = const_cast< char* >(pDbColumn->pData.get());
966 result r = DateTime::Parse(pStr, value);
967 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] Propagating to caller...", GetErrorMessage(r));
973 _DbEnumeratorImpl::GetColumnCount(void) const
975 SysTryReturn(NID_IO, __pEnum != null, -1, E_INVALID_STATE,
976 "[E_INVALID_STATE] This instance has not been properly constructed yet or has already been finalized.");
977 SysTryReturn(NID_IO, __pDbEnumeratorCache != null, -1, E_INVALID_STATE,
978 "[E_INVALID_STATE] The method has tried to fetch the column data of a result set that is not activated.");
980 return __columnCount;
984 _DbEnumeratorImpl::GetColumnType(int columnIndex) const
986 DbColumnType type = DB_COLUMNTYPE_UNDEFINED;
988 SysTryReturn(NID_IO, __pEnum != null, DB_COLUMNTYPE_UNDEFINED, E_INVALID_STATE,
989 "[E_INVALID_STATE] This instance has not been properly constructed yet or has already been finalized.");
991 SysTryReturn(NID_IO, columnIndex >= 0 && columnIndex < __columnCount, DB_COLUMNTYPE_UNDEFINED, E_INVALID_ARG,
992 "[E_INVALID_ARG] Given column index is out of range.");
994 SysTryReturn(NID_IO, __pDbEnumeratorCache != null, DB_COLUMNTYPE_UNDEFINED, E_INVALID_STATE,
995 "[E_INVALID_STATE] The method has tried to fetch the column data of a result set that is not activated.");
997 if (__pDbEnumeratorCache->__pCurrentDbRow)
999 _DbColumn* pDbColumn = dynamic_cast < _DbColumn* >(__pDbEnumeratorCache->__pCurrentDbRow->dbValuesList.GetAt(columnIndex));
1002 SetLastResult(E_INVALID_STATE);
1003 return DB_COLUMNTYPE_UNDEFINED;
1005 switch (pDbColumn->type)
1007 case SQLITE_INTEGER:
1008 type = DB_COLUMNTYPE_INT;
1012 type = DB_COLUMNTYPE_DOUBLE;
1016 type = DB_COLUMNTYPE_TEXT;
1020 type = DB_COLUMNTYPE_BLOB;
1024 type = DB_COLUMNTYPE_NULL;
1028 SetLastResult(E_INVALID_STATE);
1037 _DbEnumeratorImpl::GetColumnName(int columnIndex) const
1039 SysTryReturn(NID_IO, __pEnum != null, null, E_INVALID_STATE,
1040 "[E_INVALID_STATE] This instance has not been properly constructed yet or has already been finalized.");
1042 SysTryReturn(NID_IO, columnIndex >= 0 && columnIndex < __columnCount, null, E_INVALID_ARG,
1043 "[E_INVALID_ARG] Given column index is out of range.");
1045 SysTryReturn(NID_IO, __pDbEnumeratorCache != null, null, E_INVALID_STATE,
1046 "[E_INVALID_STATE] The method has tried to fetch the column data of a result set that is not activated.");
1048 String* pString = dynamic_cast <String *> (__pDbEnumeratorCache->__dbColumnNameList.GetAt(columnIndex));
1052 SetLastResult(E_INVALID_STATE);
1056 return String(pString->GetPointer());
1060 _DbEnumeratorImpl::GetColumnSize(int columnIndex) const
1064 SysTryReturn(NID_IO, __pEnum != null, 0, E_INVALID_STATE,
1065 "[E_INVALID_STATE] This instance has not been properly constructed yet or has already been finalized.");
1067 SysTryReturn(NID_IO, columnIndex >= 0 && columnIndex < __columnCount, 0, E_INVALID_ARG,
1068 "[E_INVALID_ARG] Given column index is out of range.");
1070 SysTryReturn(NID_IO, __pDbEnumeratorCache != null, 0, E_INVALID_STATE,
1071 "[E_INVALID_STATE] The method has tried to fetch the column data of a result set that is not activated.");
1073 if (__pDbEnumeratorCache->__pCurrentDbRow)
1075 _DbColumn* pDbColumn = dynamic_cast < _DbColumn* >(__pDbEnumeratorCache->__pCurrentDbRow->dbValuesList.GetAt(columnIndex));
1078 SetLastResult(E_INVALID_STATE);
1081 int columnType = pDbColumn->type;
1085 case SQLITE_INTEGER:
1086 if (_AppInfo::IsOspCompat())
1088 bytes = sizeof(int); // for 2.0 compatibility
1092 bytes = sizeof(long long);
1097 bytes = sizeof(double);
1103 bytes = pDbColumn->size;
1107 SetLastResult(E_INVALID_STATE);
1116 _DbEnumeratorImpl::GetInstance(DbEnumerator& dbEnumerator)
1118 return dbEnumerator.__pDbEnumeratorImpl;
1121 const _DbEnumeratorImpl*
1122 _DbEnumeratorImpl::GetInstance(const DbEnumerator& dbEnumerator)
1124 return dbEnumerator.__pDbEnumeratorImpl;
1128 _DbEnumeratorImpl::CreateDbEnumeratorInstanceN(void)
1130 unique_ptr<DbEnumerator> pDbEnumerator(new (std::nothrow) DbEnumerator());
1131 SysTryReturn(NID_IO, pDbEnumerator != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
1132 return pDbEnumerator.release();