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