1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "datashare_result_set.h"
16 
17 #include <securec.h>
18 #include <sstream>
19 
20 #include "adaptor.h"
21 #include "datashare_block_writer_impl.h"
22 #include "datashare_errno.h"
23 #include "datashare_log.h"
24 #include "parcel.h"
25 #include "shared_block.h"
26 #include "string_ex.h"
27 
28 namespace OHOS {
29 namespace DataShare {
30 namespace {
31     // The default position of the cursor
32     static const int INITIAL_POS = -1;
33     static const size_t DEFAULT_SHARE_BLOCK_SIZE = 2 * 1024 * 1024;
34 } // namespace
35 int DataShareResultSet::blockId_ = 0;
DataShareResultSet()36 DataShareResultSet::DataShareResultSet()
37 {
38 }
39 
DataShareResultSet(std::shared_ptr<ResultSetBridge> & bridge)40 DataShareResultSet::DataShareResultSet(std::shared_ptr<ResultSetBridge> &bridge)
41     : bridge_(bridge)
42 {
43     std::string name = "DataShare" + std::to_string(blockId_++);
44     blockWriter_ = std::make_shared<DataShareBlockWriterImpl>(name, DEFAULT_SHARE_BLOCK_SIZE);
45     if (blockWriter_ == nullptr) {
46         return;
47     }
48     sharedBlock_ = blockWriter_->GetBlock();
49 }
50 
~DataShareResultSet()51 DataShareResultSet::~DataShareResultSet()
52 {
53     Close();
54 }
55 
GetAllColumnNames(std::vector<std::string> & columnNames)56 int DataShareResultSet::GetAllColumnNames(std::vector<std::string> &columnNames)
57 {
58     auto bridge = GetBridge();
59     if (bridge == nullptr) {
60         LOG_ERROR("bridge_ is null!");
61         return E_ERROR;
62     }
63     return bridge->GetAllColumnNames(columnNames);
64 }
65 
GetRowCount(int & count)66 int DataShareResultSet::GetRowCount(int &count)
67 {
68     auto bridge = GetBridge();
69     if (bridge == nullptr) {
70         LOG_ERROR("bridge_ is null!");
71         return E_ERROR;
72     }
73     return bridge->GetRowCount(count);
74 }
75 
OnGo(int startRowIndex,int targetRowIndex,int * cachedIndex)76 bool DataShareResultSet::OnGo(int startRowIndex, int targetRowIndex, int *cachedIndex)
77 {
78     auto block = GetBlock();
79     auto bridge = GetBridge();
80     if (bridge == nullptr || blockWriter_ == nullptr || block == nullptr) {
81         LOG_ERROR("bridge_ or blockWriter_ or sharedBlock_ is null!");
82         return false;
83     }
84     std::vector<std::string> columnNames;
85     GetAllColumnNames(columnNames);
86     block->Clear();
87     block->SetColumnNum(columnNames.size());
88     int result = bridge->OnGo(startRowIndex, targetRowIndex, *blockWriter_);
89     if (cachedIndex != nullptr) {
90         *cachedIndex = result;
91     }
92     if (result < 0) {
93         return false;
94     }
95     return true;
96 }
97 
FillBlock(int startRowIndex,AppDataFwk::SharedBlock * block)98 void DataShareResultSet::FillBlock(int startRowIndex, AppDataFwk::SharedBlock *block)
99 {
100     return;
101 }
102 
103 /**
104  * Get current bridge
105  */
GetBridge()106 std::shared_ptr<ResultSetBridge> DataShareResultSet::GetBridge()
107 {
108     std::shared_lock<std::shared_mutex> lock(mutex_);
109     return bridge_;
110 }
111 
112 /**
113  * Get current shared block
114  */
GetBlock()115 std::shared_ptr<AppDataFwk::SharedBlock> DataShareResultSet::GetBlock()
116 {
117     std::shared_lock<std::shared_mutex> lock(mutex_);
118     return sharedBlock_;
119 }
120 
GetDataType(int columnIndex,DataType & dataType)121 int DataShareResultSet::GetDataType(int columnIndex, DataType &dataType)
122 {
123     auto block = GetBlock();
124     if (block == nullptr) {
125         LOG_ERROR("sharedBlock is null!");
126         return E_ERROR;
127     }
128     int rowCount = 0;
129     GetRowCount(rowCount);
130     AppDataFwk::SharedBlock::CellUnit *cellUnit =
131         block->GetCellUnit(static_cast<uint32_t>(rowPos_) - startRowPos_, static_cast<uint32_t>(columnIndex));
132     if (!cellUnit) {
133         return E_ERROR;
134     }
135     dataType = (DataType)cellUnit->type;
136     return E_OK;
137 }
138 
GoToRow(int position)139 int DataShareResultSet::GoToRow(int position)
140 {
141     auto block = GetBlock();
142     if (block == nullptr) {
143         LOG_ERROR("sharedBlock is null!");
144         return E_ERROR;
145     }
146     int rowCnt = 0;
147     GetRowCount(rowCnt);
148     if (position >= rowCnt) {
149         rowPos_ = rowCnt;
150         return E_ERROR;
151     }
152     if (position < 0) {
153         rowPos_ = INITIAL_POS;
154         return E_ERROR;
155     }
156     if (position == rowPos_) {
157         return E_OK;
158     }
159     bool result = true;
160     if (position > endRowPos_ || position < startRowPos_) {
161         int endPos = -1;
162         result = OnGo(position, rowCnt - 1, &endPos);
163         if (result) {
164             startRowPos_ = position;
165             endRowPos_ = endPos;
166         }
167     }
168 
169     if (!result) {
170         rowPos_ = INITIAL_POS;
171         startRowPos_ = INITIAL_POS;
172         endRowPos_ = INITIAL_POS;
173         return E_ERROR;
174     } else {
175         rowPos_ = position;
176         return E_OK;
177     }
178 }
179 
GetBlob(int columnIndex,std::vector<uint8_t> & value)180 int DataShareResultSet::GetBlob(int columnIndex, std::vector<uint8_t> &value)
181 {
182     auto block = GetBlock();
183     if (block == nullptr) {
184         LOG_ERROR("sharedBlock is null!");
185         return E_ERROR;
186     }
187     int errorCode = CheckState(columnIndex);
188     if (errorCode != E_OK) {
189         return errorCode;
190     }
191 
192     AppDataFwk::SharedBlock::CellUnit *cellUnit = block->GetCellUnit(rowPos_ - startRowPos_, columnIndex);
193     if (!cellUnit) {
194         return E_ERROR;
195     }
196 
197     value.resize(0);
198     int type = cellUnit->type;
199     if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_BLOB
200         || type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_STRING) {
201         size_t size;
202         const auto *blob = static_cast<const uint8_t *>(block->GetCellUnitValueBlob(cellUnit, &size));
203         if (size == 0 || blob == nullptr) {
204             LOG_WARN("blob data is empty!");
205         } else {
206             value.resize(size);
207             value.assign(blob, blob + size);
208         }
209         return E_OK;
210     } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_INTEGER) {
211         return E_OK;
212     } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_NULL) {
213         return E_OK;
214     } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_FLOAT) {
215         return E_OK;
216     } else {
217         LOG_ERROR("AppDataFwk::SharedBlock::nothing !");
218         return E_INVALID_OBJECT_TYPE;
219     }
220 }
221 
GetString(int columnIndex,std::string & value)222 int DataShareResultSet::GetString(int columnIndex, std::string &value)
223 {
224     auto block = GetBlock();
225     if (block == nullptr) {
226         LOG_ERROR("sharedBlock is null!");
227         return E_ERROR;
228     }
229     AppDataFwk::SharedBlock::CellUnit *cellUnit = block->GetCellUnit(rowPos_ - startRowPos_, columnIndex);
230     if (!cellUnit) {
231         return E_ERROR;
232     }
233     int type = cellUnit->type;
234     if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_STRING) {
235         size_t sizeIncludingNull;
236         value = std::string(block->GetCellUnitValueString(cellUnit, &sizeIncludingNull));
237         return E_OK;
238     } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_NULL) {
239         return E_OK;
240     } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_INTEGER) {
241         int64_t tempValue = cellUnit->cell.longValue;
242         value = std::to_string(tempValue);
243         return E_OK;
244     } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_FLOAT) {
245         double tempValue = cellUnit->cell.doubleValue;
246         std::ostringstream os;
247         if (os << tempValue) {
248             value = os.str();
249         }
250         return E_OK;
251     } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_BLOB) {
252         return E_ERROR;
253     } else {
254         LOG_ERROR("GetString is failed!");
255         return E_ERROR;
256     }
257 }
258 
GetInt(int columnIndex,int & value)259 int DataShareResultSet::GetInt(int columnIndex, int &value)
260 {
261     auto block = GetBlock();
262     if (block == nullptr) {
263         LOG_ERROR("sharedBlock is null!");
264         return E_ERROR;
265     }
266     AppDataFwk::SharedBlock::CellUnit *cellUnit = block->GetCellUnit(rowPos_ - startRowPos_, columnIndex);
267     if (!cellUnit) {
268         return E_ERROR;
269     }
270     value = (int)cellUnit->cell.longValue;
271     return E_OK;
272 }
273 
GetLong(int columnIndex,int64_t & value)274 int DataShareResultSet::GetLong(int columnIndex, int64_t &value)
275 {
276     auto block = GetBlock();
277     if (block == nullptr) {
278         LOG_ERROR("sharedBlock is null!");
279         return E_ERROR;
280     }
281     AppDataFwk::SharedBlock::CellUnit *cellUnit = block->GetCellUnit(rowPos_ - startRowPos_, columnIndex);
282     if (!cellUnit) {
283         return E_ERROR;
284     }
285 
286     int type = cellUnit->type;
287 
288     if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_INTEGER) {
289         value = cellUnit->cell.longValue;
290         return E_OK;
291     } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_STRING) {
292         size_t sizeIncludingNull;
293         const char *tempValue = block->GetCellUnitValueString(cellUnit, &sizeIncludingNull);
294         value = ((sizeIncludingNull > 1) && (tempValue != nullptr)) ? long(strtoll(tempValue, nullptr, 0)) : 0L;
295         return E_OK;
296     } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_FLOAT) {
297         value = (int64_t)cellUnit->cell.doubleValue;
298         return E_OK;
299     } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_NULL) {
300         value = 0L;
301         return E_OK;
302     } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_BLOB) {
303         value = 0L;
304         return E_OK;
305     } else {
306         LOG_ERROR("Nothing !");
307         return E_INVALID_OBJECT_TYPE;
308     }
309 }
310 
GetDouble(int columnIndex,double & value)311 int DataShareResultSet::GetDouble(int columnIndex, double &value)
312 {
313     auto block = GetBlock();
314     if (block == nullptr) {
315         LOG_ERROR("sharedBlock is null!");
316         return E_ERROR;
317     }
318     int errorCode = CheckState(columnIndex);
319     if (errorCode != E_OK) {
320         return errorCode;
321     }
322     AppDataFwk::SharedBlock::CellUnit *cellUnit = block->GetCellUnit(rowPos_ - startRowPos_, columnIndex);
323     if (!cellUnit) {
324         return E_ERROR;
325     }
326     int type = cellUnit->type;
327     if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_FLOAT) {
328         value = cellUnit->cell.doubleValue;
329         return E_OK;
330     } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_STRING) {
331         size_t sizeIncludingNull;
332         const char *tempValue = block->GetCellUnitValueString(cellUnit, &sizeIncludingNull);
333         value = ((sizeIncludingNull > 1) && (tempValue != nullptr)) ? strtod(tempValue, nullptr) : 0.0;
334         return E_OK;
335     } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_INTEGER) {
336         value = static_cast<double>(cellUnit->cell.longValue);
337         return E_OK;
338     } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_NULL) {
339         value = 0.0;
340         return E_OK;
341     } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_BLOB) {
342         value = 0.0;
343         return E_OK;
344     } else {
345         LOG_ERROR("AppDataFwk::SharedBlock::nothing !");
346         value = 0.0;
347         return E_INVALID_OBJECT_TYPE;
348     }
349 }
350 
IsColumnNull(int columnIndex,bool & isNull)351 int DataShareResultSet::IsColumnNull(int columnIndex, bool &isNull)
352 {
353     auto block = GetBlock();
354     if (block == nullptr) {
355         LOG_ERROR("sharedBlock is null!");
356         return E_ERROR;
357     }
358     int errorCode = CheckState(columnIndex);
359     if (errorCode != E_OK) {
360         return errorCode;
361     }
362     AppDataFwk::SharedBlock::CellUnit *cellUnit = block->GetCellUnit(rowPos_ - startRowPos_, columnIndex);
363     if (!cellUnit) {
364         return E_ERROR;
365     }
366     if (cellUnit->type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_NULL) {
367         isNull = true;
368         return E_OK;
369     }
370     isNull = false;
371     return E_OK;
372 }
373 
Close()374 int DataShareResultSet::Close()
375 {
376     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
377     DataShareAbsResultSet::Close();
378     ClosedBlockAndBridge();
379     return E_OK;
380 }
381 
382 /**
383  * Allocates a new shared block to an {@link DataShareResultSet}
384  */
SetBlock(AppDataFwk::SharedBlock * block)385 void DataShareResultSet::SetBlock(AppDataFwk::SharedBlock *block)
386 {
387     std::unique_lock<std::shared_mutex> lock(mutex_);
388     if (sharedBlock_ != nullptr) {
389         if (sharedBlock_.get() != block) {
390             sharedBlock_ = std::shared_ptr<AppDataFwk::SharedBlock>(block);
391         }
392     } else {
393         if (block != nullptr) {
394             sharedBlock_ = std::shared_ptr<AppDataFwk::SharedBlock>(block);
395         }
396     }
397 }
398 
399 /**
400  * Checks whether an {@code DataShareResultSet} object contains shared blocks
401  */
HasBlock()402 bool DataShareResultSet::HasBlock()
403 {
404     return GetBlock() != nullptr;
405 }
406 
407 /**
408  * Closes a shared block that is not empty in this {@code DataShareResultSet} object
409  */
ClosedBlockAndBridge()410 void DataShareResultSet::ClosedBlockAndBridge()
411 {
412     std::unique_lock<std::shared_mutex> lock(mutex_);
413     sharedBlock_ = nullptr;
414     bridge_ = nullptr;
415 }
416 
Finalize()417 void DataShareResultSet::Finalize()
418 {
419     Close();
420 }
421 
422 /**
423  * Check current status
424  */
CheckState(int columnIndex)425 int DataShareResultSet::CheckState(int columnIndex)
426 {
427     int cnt = 0;
428     GetColumnCount(cnt);
429     if (columnIndex >= cnt || columnIndex < 0) {
430         return E_INVALID_COLUMN_INDEX;
431     }
432     if (rowPos_ == INITIAL_POS) {
433         return E_INVALID_STATEMENT;
434     }
435     return E_OK;
436 }
437 
Marshalling(MessageParcel & parcel)438 bool DataShareResultSet::Marshalling(MessageParcel &parcel)
439 {
440     auto block = GetBlock();
441     if (block == nullptr) {
442         LOG_ERROR("sharedBlock is null.");
443         return false;
444     }
445     return block->WriteMessageParcel(parcel);
446 }
447 
Unmarshalling(MessageParcel & parcel)448 bool DataShareResultSet::Unmarshalling(MessageParcel &parcel)
449 {
450     auto block = GetBlock();
451     if (block != nullptr) {
452         LOG_ERROR("sharedBlock is not null.");
453         return false;
454     }
455     AppDataFwk::SharedBlock *sharedBlock = nullptr;
456     int result = AppDataFwk::SharedBlock::ReadMessageParcel(parcel, sharedBlock);
457     SetBlock(sharedBlock);
458     if (result < 0) {
459         LOG_ERROR("create from parcel error is %{public}d.", result);
460     }
461     return true;
462 }
463 } // namespace DataShare
464 } // namespace OHOS