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