1 /*
2  * Copyright (c) 2021 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 #define LOG_TAG "AbsSharedResultSet"
16 #include "abs_shared_result_set.h"
17 
18 #include <securec.h>
19 
20 #include <algorithm>
21 #include <codecvt>
22 #include <iostream>
23 #include <sstream>
24 #include <string>
25 
26 #include "logger.h"
27 #include "raw_data_parser.h"
28 #include "rdb_errno.h"
29 #include "rdb_trace.h"
30 #include "shared_block.h"
31 
32 namespace OHOS {
33 namespace NativeRdb {
34 using namespace OHOS::Rdb;
35 using SharedBlock = AppDataFwk::SharedBlock;
AbsSharedResultSet(std::string name)36 AbsSharedResultSet::AbsSharedResultSet(std::string name) : sharedBlock_(nullptr), sharedBlockName_(std::move(name))
37 {
38 }
39 
AbsSharedResultSet()40 AbsSharedResultSet::AbsSharedResultSet()
41 {
42 }
43 
~AbsSharedResultSet()44 AbsSharedResultSet::~AbsSharedResultSet()
45 {
46     ClosedBlock();
47 }
48 
GetRowCount(int & count)49 int AbsSharedResultSet::GetRowCount(int &count)
50 {
51     return AbsResultSet::GetRowCount(count);
52 }
53 
OnGo(int oldRowIndex,int newRowIndex)54 int32_t AbsSharedResultSet::OnGo(int oldRowIndex, int newRowIndex)
55 {
56     return E_OK;
57 }
58 
59 /**
60  * Get current shared block
61  */
GetBlock()62 std::shared_ptr<SharedBlock> AbsSharedResultSet::GetBlock()
63 {
64     std::lock_guard<decltype(globalMtx_)> lockGuard(globalMtx_);
65     if (sharedBlock_ != nullptr || isClosed_ || lowMem_) {
66         return sharedBlock_;
67     }
68     SharedBlock *block = nullptr;
69     auto errcode = SharedBlock::Create(sharedBlockName_, DEFAULT_BLOCK_SIZE, block);
70     if (errcode != SharedBlock::SHARED_BLOCK_OK) {
71         lowMem_ = true;
72         return nullptr;
73     }
74     sharedBlock_ = std::shared_ptr<SharedBlock>(block);
75     return sharedBlock_;
76 }
77 
GetColumnType(int columnIndex,ColumnType & columnType)78 int AbsSharedResultSet::GetColumnType(int columnIndex, ColumnType &columnType)
79 {
80     auto block = GetBlock();
81     int errorCode = CheckState(columnIndex);
82     if (errorCode != E_OK) {
83         return errorCode;
84     }
85     SharedBlock::CellUnit* cellUnit = block->GetCellUnit(block->GetBlockPos(), (uint32_t)columnIndex);
86     if (!cellUnit) {
87         LOG_ERROR("AbsSharedResultSet::GetColumnType cellUnit is null!");
88         return E_ERROR;
89     }
90     columnType = (ColumnType)cellUnit->type;
91     return E_OK;
92 }
93 
UpdateBlockPos(int position,int rowCnt)94 int AbsSharedResultSet::UpdateBlockPos(int position, int rowCnt)
95 {
96     auto block = GetBlock();
97     auto ret = OnGo(rowPos_, position);
98     if (ret == E_OK) {
99         uint32_t startPos = block->GetStartPos();
100         uint32_t blockPos = block->GetBlockPos();
101         if (static_cast<uint32_t>(position) != startPos + blockPos) {
102             block->SetBlockPos(position - startPos);
103         }
104     }
105     return ret;
106 }
107 
GoToRow(int position)108 int AbsSharedResultSet::GoToRow(int position)
109 {
110     if (isClosed_) {
111         return E_ALREADY_CLOSED;
112     }
113 
114     int rowCnt = 0;
115     auto ret = GetRowCount(rowCnt);
116     if (ret != E_OK) {
117         LOG_ERROR("GetRowCount ret is %{public}d, rowCount is %{public}d", ret, rowCnt);
118         return ret;
119     }
120 
121     if (position >= rowCnt || position < 0) {
122         rowPos_ = (position >= rowCnt && rowCnt != 0) ? rowCnt : rowPos_;
123         LOG_DEBUG("position[%{public}d] rowCnt[%{public}d] rowPos[%{public}d]!", position, rowCnt, rowPos_);
124         return E_ROW_OUT_RANGE;
125     }
126 
127     if (position == rowPos_) {
128         return E_OK;
129     }
130 
131     ret = UpdateBlockPos(position, rowCnt);
132     if (ret == E_OK) {
133         rowPos_ = position;
134     }
135     return ret;
136 }
137 
GetString(int columnIndex,std::string & value)138 int AbsSharedResultSet::GetString(int columnIndex, std::string &value)
139 {
140     return AbsResultSet::GetString(columnIndex, value);
141 }
142 
Get(int32_t col,ValueObject & value)143 int AbsSharedResultSet::Get(int32_t col, ValueObject& value)
144 {
145     auto block = GetBlock();
146     int errorCode = CheckState(col);
147     if (errorCode != E_OK || block == nullptr) {
148         return errorCode;
149     }
150 
151     auto *cellUnit = block->GetCellUnit(block->GetBlockPos(), col);
152     if (cellUnit == nullptr) {
153         LOG_ERROR("cellUnit is null, col is %{public}d!", col);
154         return E_ERROR;
155     }
156     switch (cellUnit->type) {
157         case SharedBlock::CELL_UNIT_TYPE_NULL:
158             break;
159         case SharedBlock::CELL_UNIT_TYPE_INTEGER:
160             value = cellUnit->cell.longValue;
161             break;
162         case SharedBlock::CELL_UNIT_TYPE_FLOAT:
163             value = cellUnit->cell.doubleValue;
164             break;
165         case SharedBlock::CELL_UNIT_TYPE_STRING:
166             value = cellUnit->GetString(block.get());
167             break;
168         case SharedBlock::CELL_UNIT_TYPE_BLOB:
169             value = cellUnit->GetBlob(block.get());
170             break;
171         default:
172             return GetCustomerValue(col, value, block.get());
173     }
174     return E_OK;
175 }
176 
GetSize(int columnIndex,size_t & size)177 int AbsSharedResultSet::GetSize(int columnIndex, size_t &size)
178 {
179     size = 0;
180     auto block = GetBlock();
181     int errorCode = CheckState(columnIndex);
182     if (errorCode != E_OK) {
183         return errorCode;
184     }
185 
186     auto *cellUnit = block->GetCellUnit(GetBlock()->GetBlockPos(), columnIndex);
187     if (cellUnit == nullptr) {
188         LOG_ERROR("cellUnit is null!");
189         return E_ERROR;
190     }
191 
192     int type = cellUnit->type;
193     if (type == SharedBlock::CELL_UNIT_TYPE_STRING
194         || type == SharedBlock::CELL_UNIT_TYPE_BLOB
195         || type == SharedBlock::CELL_UNIT_TYPE_NULL) {
196         size = cellUnit->cell.stringOrBlobValue.size;
197         return E_OK;
198     }
199 
200     return E_INVALID_OBJECT_TYPE;
201 }
202 
Close()203 int AbsSharedResultSet::Close()
204 {
205     if (!isClosed_) {
206         AbsResultSet::Close();
207         ClosedBlock();
208         auto name = std::move(sharedBlockName_);
209     }
210     return E_OK;
211 }
212 
213 /**
214  * Allocates a new shared block to an {@link AbsSharedResultSet}
215  */
SetBlock(SharedBlock * block)216 void AbsSharedResultSet::SetBlock(SharedBlock *block)
217 {
218     std::lock_guard<decltype(globalMtx_)> lockGuard(globalMtx_);
219     if (sharedBlock_.get() != block) {
220         sharedBlock_ = std::shared_ptr<SharedBlock>(block);
221     }
222 }
223 
224 /**
225  * Checks whether an {@code AbsSharedResultSet} object contains shared blocks
226  */
HasBlock()227 bool AbsSharedResultSet::HasBlock()
228 {
229     return GetBlock() != nullptr;
230 }
231 
232 /**
233  * Closes a shared block that is not empty in this {@code AbsSharedResultSet} object
234  */
ClosedBlock()235 void AbsSharedResultSet::ClosedBlock()
236 {
237     std::lock_guard<decltype(globalMtx_)> lockGuard(globalMtx_);
238     sharedBlock_ = nullptr;
239 }
240 
ClearBlock()241 void AbsSharedResultSet::ClearBlock()
242 {
243     auto block = GetBlock();
244     if (block != nullptr) {
245         block->Clear();
246     }
247 }
248 
Finalize()249 void AbsSharedResultSet::Finalize()
250 {
251     Close();
252 }
253 
GetCustomerValue(int index,ValueObject & value,SharedBlock * block)254 int AbsSharedResultSet::GetCustomerValue(int index, ValueObject& value, SharedBlock *block)
255 {
256     auto *cellUnit = block->GetCellUnit(block->GetBlockPos(), index);
257     if (cellUnit == nullptr) {
258         LOG_ERROR("cellUnit is null, col is %{public}d!", index);
259         return E_ERROR;
260     }
261 
262     size_t size = cellUnit->cell.stringOrBlobValue.size;
263     auto data = cellUnit->GetRawData(block);
264     switch (cellUnit->type) {
265         case SharedBlock::CELL_UNIT_TYPE_ASSET: {
266             ValueObject::Asset asset;
267             RawDataParser::ParserRawData(data, size, asset);
268             value = std::move(asset);
269             break;
270         }
271         case SharedBlock::CELL_UNIT_TYPE_ASSETS: {
272             ValueObject::Assets assets;
273             RawDataParser::ParserRawData(data, size, assets);
274             value = std::move(assets);
275             break;
276         }
277         case SharedBlock::CELL_UNIT_TYPE_FLOATS: {
278             ValueObject::FloatVector floats;
279             RawDataParser::ParserRawData(data, size, floats);
280             value = std::move(floats);
281             break;
282         }
283         case SharedBlock::CELL_UNIT_TYPE_BIGINT: {
284             ValueObject::BigInt bigInt;
285             RawDataParser::ParserRawData(data, size, bigInt);
286             value = std::move(bigInt);
287             break;
288         }
289         default:
290             LOG_ERROR("invalid type is %{public}d, col is %{public}d!", cellUnit->type, index);
291             return E_INVALID_OBJECT_TYPE;
292     }
293     return E_OK;
294 }
295 
296 /**
297  * Check current status
298  */
CheckState(int columnIndex)299 int AbsSharedResultSet::CheckState(int columnIndex)
300 {
301     if (isClosed_) {
302         return E_ALREADY_CLOSED;
303     }
304     if (GetBlock() == nullptr) {
305         LOG_ERROR("sharedBlock is null!");
306         return E_ERROR;
307     }
308     int count = 0;
309     GetRowCount(count);
310     if (rowPos_ < 0 || rowPos_ >= count) {
311         return E_ROW_OUT_RANGE;
312     }
313 
314     GetColumnCount(count);
315     if (columnIndex >= count || columnIndex < 0) {
316         return E_COLUMN_OUT_RANGE;
317     }
318 
319     return E_OK;
320 }
321 } // namespace NativeRdb
322 } // namespace OHOS
323