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