sync with master
[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                 case DB_COLUMNTYPE_NULL:
239                 {
240                         type = 5; // null type
241                         break;
242                 }
243
244                 default:
245                         SysLog(NID_IO, "type: UNDEFINED (%d)", type);
246                         break;
247                 }
248                 r = pFile->Write(&type, sizeof(int));
249                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
250
251                 totalSizeOfColumnTypes += sizeof(int);
252         }
253         //totalSizeOfColumnTypes = columnCount * sizeof(int);
254
255         totalSizeOfColumnNames = 0;
256         for (i = 0; i < columnCount; i++)
257         {
258                 char* pColumnName = null;
259                 int byte = 0;
260
261                 columnName = pDbEnum->GetColumnName(i);
262                 columnName.Append('\n');
263                 r = pFile->Write(columnName);
264                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
265
266                 pColumnName = _StringConverter::CopyToCharArrayN(columnName);
267                 byte = strlen(pColumnName);
268                 totalSizeOfColumnNames += byte;
269
270                 SysLog(NID_IO, "[%d] column name: %s", i, pColumnName);
271                 delete[] pColumnName;
272         }
273         r = pFile->Seek(FILESEEKPOSITION_BEGIN, sizeof(int) * 2);
274         SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
275
276         r = pFile->Write(&totalSizeOfColumnNames, sizeof(int)); // pack
277         SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
278
279         r = pFile->Seek(FILESEEKPOSITION_CURRENT, totalSizeOfColumnTypes + totalSizeOfColumnNames);
280         SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
281
282         do
283         {
284                 for (i = 0; i < columnCount; i++)
285                 {
286                         DbColumnType columnType = pDbEnum->GetColumnType(i);
287                         switch (columnType)
288                         {
289                         case DB_COLUMNTYPE_INT:
290                         {
291                                 long long int64Value = 0;
292                                 int type = 1; // int64
293                                 int size = 0;
294
295                                 r = pDbEnum->GetInt64At(i, int64Value);
296                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
297
298                                 size = sizeof(long long);
299
300                                 r = pFile->Write(&type, sizeof(int));
301                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
302
303                                 r = pFile->Write(&size, sizeof(int));
304                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
305                                 r = pFile->Write(&int64Value, sizeof(long long));
306                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
307                                 break;
308                         }
309
310                         case DB_COLUMNTYPE_DOUBLE:
311                         {
312                                 double doubleValue = 0;
313                                 int type = 2; // double
314                                 int size = 0;
315
316                                 r = pDbEnum->GetDoubleAt(i, doubleValue);
317                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
318
319                                 size = sizeof(double);
320
321                                 r = pFile->Write(&type, sizeof(int));
322                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
323
324                                 r = pFile->Write(&size, sizeof(int));
325                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
326
327                                 r = pFile->Write(&doubleValue, sizeof(double));
328                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
329                                 break;
330                         }
331
332                         case DB_COLUMNTYPE_TEXT:
333                         {
334                                 String textValue;
335                                 int type = 3; // text
336                                 int size = 0;
337
338                                 r = pDbEnum->GetStringAt(i, textValue);
339                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
340
341                                 std::unique_ptr<char[]> pContent(_StringConverter::CopyToCharArrayN(textValue));
342                                 size = strlen(pContent.get());
343
344                                 r = pFile->Write(&type, sizeof(int));
345                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
346
347                                 r = pFile->Write(&size, sizeof(int));
348                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
349
350                                 if (size > 0)
351                                 {
352                                         r = pFile->Write(pContent.get(), size);
353                                         SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
354                                 }
355                                 break;
356                         }
357
358                         case DB_COLUMNTYPE_BLOB: // XXX: need test !!
359                         {
360                                 ByteBuffer blobValue;
361                                 int type = 4; // blob
362                                 int size = 0;
363
364                                 size = pDbEnum->GetColumnSize(i);
365                                 r = blobValue.Construct(size);
366                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
367
368                                 r = pDbEnum->GetBlobAt(i, blobValue);
369                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
370
371                                 r = pFile->Write(&type, sizeof(int));
372                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
373
374                                 r = pFile->Write(&size, sizeof(int));
375                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
376
377                                 if (size > 0)
378                                 {
379                                         r = pFile->Write(blobValue);
380                                         SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
381                                 }
382                                 break;
383                         }
384
385                         case DB_COLUMNTYPE_NULL:
386                         {
387                                 int type = 5; // null
388                                 int size = 0;
389
390                                 r = pFile->Write(&type, sizeof(int));
391                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
392
393                                 r = pFile->Write(&size, sizeof(int));
394                                 SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
395                                 break;
396                         }
397
398                         default:
399                                 SysTryReturnResult(NID_IO, false, E_DATABASE,
400                                                    "The column type is invalid.");
401                                 break;
402                         }
403                 }
404                 rowCount++;
405         }
406         while (pDbEnum->MoveNext() == E_SUCCESS && rowCount < __countPerPage);
407
408         SysLog(NID_IO, "row count is %d.\n", rowCount);
409         r = pFile->Seek(FILESEEKPOSITION_BEGIN, 0);
410         SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
411
412         r = pFile->Write(&rowCount, sizeof(int)); // pack row count
413         SysTryReturn(NID_IO, r == E_SUCCESS, r, r, "[%s] System error was occurred.", GetErrorMessage(r));
414
415         return r;
416 }
417
418 result
419 _DataControlResultSetImpl::SetCapacity(int pageNo, int countPerPage)
420 {
421         result r = E_SUCCESS;
422
423         SysAssertf(__constructed == true, "Not yet constructed. Construct() should be called before use.\n\n");
424
425         __pageNo = pageNo;
426         __countPerPage = countPerPage;
427
428         return r;
429 }
430
431 }} // Tizen::Io
432