sync with tizen_2.0
[platform/framework/native/appfw.git] / src / io / FIo_DataControlResultSetImpl.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
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
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
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.
16 //
17
18 /**
19  * @file        FIo_DataControlResultSetImpl.cpp
20  * @brief       This is the implementation for the %_DataControlResultSetImpl class.
21  */
22
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <sys/types.h>
26 #include <new>
27 #include <unique_ptr.h>
28
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 <FBaseResult.h>
36 #include <FIoDatabase.h>
37 #include <FIoDbEnumerator.h>
38 #include <FBaseColAllElementsDeleter.h>
39 #include <FBaseSysLog.h>
40
41 #include <FBase_StringConverter.h>
42 #include <FBase_NativeError.h>
43 #include <FApp_AppControlManager.h>
44 #include <FApp_AppArg.h>
45 #include <FIo_FileImpl.h>
46 #include <FIo_DataControlResultSetImpl.h>
47
48 using namespace Tizen::Base;
49 using namespace Tizen::Base::Utility;
50 using namespace Tizen::Base::Collection;
51 using namespace Tizen::App;
52
53 const char* _DATACONTROL_RESULTSET_DIR = "/tmp/osp/DataControlResultSet/\0";
54
55 namespace Tizen { namespace Io
56 {
57
58 _DataControlResultSetImpl::_DataControlResultSetImpl(RequestId reqId)
59         : __constructed(true)
60         , __pageNo(1)
61         , __countPerPage(0)
62         , __result(E_SUCCESS)
63         , __tmpPath("")
64         , __reqId(reqId)
65 {
66 }
67
68 _DataControlResultSetImpl::~_DataControlResultSetImpl(void)
69 {
70         __constructed = false;
71 }
72
73 // header
74 // [sizeof(int)] row count
75 // [sizeof(int)] column count
76 // [sieeof(int)] total size of column names
77 //
78 // column info.
79 // [sizeof(int)] column type x N
80 // [  variant  ] column name x N
81 //
82 // column elements
83 // [sizeof(int)] type
84 // [sizeof(int)] size
85 // [  varient  ] content
86 result
87 _DataControlResultSetImpl::FillWith(IDbEnumerator* pDbEnum)
88 {
89         String tempFilePath(_DATACONTROL_RESULTSET_DIR);
90         String columnName;
91         String* pAppId = null;
92         String* pRequestType = null;
93         String* pReqId = null;
94         String* pNo = null;
95         String* pCount = null;
96         String* pColumnCount = null;
97         result r = E_SUCCESS;
98         _DataControlRequestType requestType = _DATACONTROL_REQUEST_TYPE_UNDEFINED;
99         int columnCount = 0;
100         int rowCount = 0;
101         int totalSizeOfColumnTypes = 0;
102         int totalSizeOfColumnNames = 0;
103         int cursorOffset = 0;
104         int pageNo = 0;
105         int countPerPage = 0;
106         int type = 0;
107         int i = 0;
108         int pageNoIndex = 0;
109
110         SysAssertf(__constructed == true, "Not yet constructed. Construct() should be called before use.\n\n");
111
112         _AppControlManager* pAppMgr = _AppControlManager::GetInstance();
113         SysTryReturnResult(NID_APP, pAppMgr, E_SYSTEM, "Failed to get instance.");
114
115         _ResultInfo* pResultInfo = pAppMgr->__resultManager.FindItem(static_cast< int >(__reqId));
116         SysTryReturnResult(NID_APP, pResultInfo, E_OBJ_NOT_FOUND,
117                         "The data control request specified with the reqId (%ld) did not exist.", __reqId);
118
119         const _AppArg& arg = pResultInfo->arg;
120
121         std::unique_ptr<ArrayList, AllElementsDeleter> pList(arg.GetArgListN(0));
122         SysTryReturnResult(NID_APP, pList, E_SYSTEM, "Invalid result object.");
123
124         // key-based request
125         pAppId = dynamic_cast< String* >(pList->GetAt(0)); // key[0]
126         SysTryReturnResult(NID_APP, pAppId, E_SYSTEM, "Invalid request.");
127
128         pRequestType = dynamic_cast< String* >(pList->GetAt(1)); // key[1]
129         SysTryReturnResult(NID_APP, pRequestType, E_SYSTEM, "Invalid request.");
130         Integer::Parse(*pRequestType, type);
131         requestType = static_cast< _DataControlRequestType >(type);
132         SysTryReturnResult(NID_APP, requestType ==  _DATACONTROL_REQUEST_TYPE_SQL_QUERY, E_INVALID_ARG,
133                         "The reqId should be for the data control query request.");
134
135         pReqId = dynamic_cast< String* >(pList->GetAt(2)); // key[2]
136         SysTryReturnResult(NID_APP, pReqId, E_SYSTEM, "Invalid request.");
137
138         // list-based request
139         pColumnCount = dynamic_cast< String* >(pList->GetAt(5));
140         SysTryReturnResult(NID_APP, pColumnCount, E_SYSTEM, "Invalid result object.");
141         Integer::Parse(*pColumnCount, columnCount);
142
143         pageNoIndex = 5 + columnCount + 2 + 1;
144
145         pNo = dynamic_cast< String* >(pList->GetAt(pageNoIndex));
146         SysTryReturnResult(NID_APP, pNo, E_SYSTEM, "Invalid result object.");
147         Integer::Parse(*pNo, pageNo);
148
149         pCount = dynamic_cast< String* >(pList->GetAt(pageNoIndex + 1));
150         SysTryReturnResult(NID_APP, pCount, E_SYSTEM, "Invalid result object.");
151         Integer::Parse(*pCount, countPerPage);
152
153         this->SetCapacity(pageNo, countPerPage);
154         tempFilePath.Append(*pAppId);
155         tempFilePath.Append(*pReqId);
156         __tmpPath = tempFilePath;
157
158         // initialize
159         r = pDbEnum->Reset();
160         SysTryReturnResult(NID_IO, r == E_SUCCESS, E_DATABASE,
161                         "The database engine has failed to execute reset.");
162
163         cursorOffset = (__pageNo - 1) * __countPerPage;
164         for (i = 0; i < cursorOffset; i++) // move cursor to the specific page to be requested
165         {
166                 r = pDbEnum->MoveNext();
167                 if (r == E_OUT_OF_RANGE) // the previous pages do not exist
168                 {
169                         __result = E_OUT_OF_RANGE;
170                         SysTryReturnResult(NID_APP, false, E_SUCCESS, "Out of range error.");
171                 }
172                 SysTryReturnResult(NID_IO, !IsFailed(r), E_DATABASE,
173                                    "The database engine has failed to enumerator result set.");
174         }
175
176         // XXX: must call MoveNext() before calling GetColumnCount()
177         r = pDbEnum->MoveNext();
178         if (r == E_OUT_OF_RANGE) // the specific page is empty
179         {
180                 __result = E_OUT_OF_RANGE;
181                 SysTryReturnResult(NID_APP, false, E_SUCCESS, "Out of range error.");
182         }
183         SysTryReturnResult(NID_IO, !IsFailed(r), E_DATABASE,
184                            "The database engine has failed to enumerate the result set.");
185
186         // if has the result set
187         std::unique_ptr<File> pFile(new (std::nothrow) File());
188
189         SysTryReturnResult(NID_IO, pFile != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
190
191         r = pFile->Construct(__tmpPath, "w+", true);
192         SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] Failed to create temp file (%ls) for result set.",
193                         GetErrorMessage(r), __tmpPath.GetPointer());
194
195         columnCount = pDbEnum->GetColumnCount();
196         SysLog(NID_IO, "column count is %d.\n", columnCount);
197
198         r = pFile->Seek(FILESEEKPOSITION_BEGIN, sizeof(int));
199         SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
200
201         r = pFile->Write(&columnCount, sizeof(int)); // pack column count
202         SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
203
204         r = pFile->Seek(FILESEEKPOSITION_CURRENT, sizeof(int));
205         SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
206
207         // pack column type
208         for (i = 0; i < columnCount; i++)
209         {
210                 int type = -1;
211                 DbColumnType columnType = pDbEnum->GetColumnType(i);
212                 switch (columnType)
213                 {
214                 case DB_COLUMNTYPE_INT:
215                 {
216                         type = 1; // int64 type
217                         break;
218                 }
219
220                 case DB_COLUMNTYPE_DOUBLE:
221                 {
222                         type = 2; // double type
223                         break;
224                 }
225
226                 case DB_COLUMNTYPE_TEXT:
227                 {
228                         type = 3; // text type
229                         break;
230                 }
231
232                 case DB_COLUMNTYPE_BLOB:
233                 {
234                         type = 4; // blob type
235                         break;
236                 }
237
238                 default:
239                         SysLog(NID_IO, "type: UNDEFINDE (%d)", type);
240                         break;
241                 }
242                 r = pFile->Write(&type, sizeof(int));
243                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
244
245                 totalSizeOfColumnTypes += sizeof(int);
246         }
247         //totalSizeOfColumnTypes = columnCount * sizeof(int);
248
249         totalSizeOfColumnNames = 0;
250         for (i = 0; i < columnCount; i++)
251         {
252                 char* pColumnName = null;
253                 int byte = 0;
254
255                 columnName = pDbEnum->GetColumnName(i);
256                 columnName.Append('\n');
257                 r = pFile->Write(columnName);
258                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
259
260                 pColumnName = _StringConverter::CopyToCharArrayN(columnName);
261                 byte = strlen(pColumnName);
262                 totalSizeOfColumnNames += byte;
263
264                 SysLog(NID_IO, "[%d] column name: %s", i, pColumnName);
265                 delete[] pColumnName;
266         }
267         r = pFile->Seek(FILESEEKPOSITION_BEGIN, sizeof(int) * 2);
268         SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
269
270         r = pFile->Write(&totalSizeOfColumnNames, sizeof(int)); // pack
271         SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
272
273         r = pFile->Seek(FILESEEKPOSITION_CURRENT, totalSizeOfColumnTypes + totalSizeOfColumnNames);
274         SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
275
276         do
277         {
278                 for (i = 0; i < columnCount; i++)
279                 {
280                         DbColumnType columnType = pDbEnum->GetColumnType(i);
281                         switch (columnType)
282                         {
283                         case DB_COLUMNTYPE_INT:
284                         {
285                                 long long int64Value = 0;
286                                 int type = 1; // int64
287                                 int size = 0;
288
289                                 r = pDbEnum->GetInt64At(i, int64Value);
290                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
291
292                                 size = sizeof(long long);
293
294                                 r = pFile->Write(&type, sizeof(int));
295                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
296
297                                 r = pFile->Write(&size, sizeof(int));
298                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
299
300                                 r = pFile->Write(&int64Value, sizeof(long long));
301                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
302                                 break;
303                         }
304
305                         case DB_COLUMNTYPE_DOUBLE:
306                         {
307                                 double doubleValue = 0;
308                                 int type = 2; // double
309                                 int size = 0;
310
311                                 r = pDbEnum->GetDoubleAt(i, doubleValue);
312                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
313
314                                 size = sizeof(double);
315
316                                 r = pFile->Write(&type, sizeof(int));
317                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
318
319                                 r = pFile->Write(&size, sizeof(int));
320                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
321
322                                 r = pFile->Write(&doubleValue, sizeof(double));
323                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
324                                 break;
325                         }
326
327                         case DB_COLUMNTYPE_TEXT:
328                         {
329                                 String textValue;
330                                 int type = 3; // text
331                                 int size = 0;
332
333                                 r = pDbEnum->GetStringAt(i, textValue);
334                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
335
336                                 std::unique_ptr<char[]> pContent(_StringConverter::CopyToCharArrayN(textValue));
337                                 size = strlen(pContent.get());
338
339                                 r = pFile->Write(&type, sizeof(int));
340                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
341
342                                 r = pFile->Write(&size, sizeof(int));
343                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
344
345                                 r = pFile->Write(pContent.get(), size);
346                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
347
348                                 break;
349                         }
350
351                         case DB_COLUMNTYPE_BLOB: // XXX: need test !!
352                         {
353                                 ByteBuffer blobValue;
354                                 int type = 4; // blob
355                                 int size = 0;
356
357                                 size = pDbEnum->GetColumnSize(i);
358                                 r = blobValue.Construct(size);
359                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
360
361                                 r = pDbEnum->GetBlobAt(i, blobValue);
362                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
363
364                                 r = pFile->Write(&type, sizeof(int));
365                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
366
367                                 r = pFile->Write(&size, sizeof(int));
368                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
369
370                                 r = pFile->Write(blobValue);
371                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
372                                 break;
373                         }
374
375                         default:
376                                 SysTryReturnResult(NID_IO, false, E_DATABASE,
377                                                    "The column type is invalid.");
378                                 break;
379                         }
380                 }
381                 rowCount++;
382         }
383         while (pDbEnum->MoveNext() == E_SUCCESS && rowCount < __countPerPage);
384
385         SysLog(NID_IO, "row count is %d.\n", rowCount);
386         r = pFile->Seek(FILESEEKPOSITION_BEGIN, 0);
387         SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
388
389         r = pFile->Write(&rowCount, sizeof(int)); // pack row count
390         SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
391
392         return r;
393 }
394
395 result
396 _DataControlResultSetImpl::SetCapacity(int pageNo, int countPerPage)
397 {
398         result r = E_SUCCESS;
399
400         SysAssertf(__constructed == true, "Not yet constructed. Construct() should be called before use.\n\n");
401
402         __pageNo = pageNo;
403         __countPerPage = countPerPage;
404
405         return r;
406 }
407
408 }} // Tizen::Io
409