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 
16 #define LOG_TAG "RdbResultSetImpl"
17 
18 #include "rdb_result_set_impl.h"
19 
20 #include <mutex>
21 
22 #include "log_print.h"
23 #include "store/cursor.h"
24 #include "store_types.h"
25 
26 using DistributedDB::DBStatus;
27 using OHOS::NativeRdb::ColumnType;
28 
29 namespace OHOS::DistributedRdb {
30 using OHOS::DistributedData::GeneralError;
31 using Cursor = OHOS::DistributedData::Cursor;
32 using namespace OHOS::NativeRdb;
RdbResultSetImpl(std::shared_ptr<Cursor> resultSet)33 RdbResultSetImpl::RdbResultSetImpl(std::shared_ptr<Cursor> resultSet) : resultSet_(std::move(resultSet))
34 {
35     if (resultSet_ != nullptr) {
36         count_ = resultSet_->GetCount();
37         resultSet_->GetColumnNames(colNames_);
38     }
39 }
40 
GetAllColumnNames(std::vector<std::string> &columnNames)41 int RdbResultSetImpl::GetAllColumnNames(std::vector<std::string> &columnNames)
42 {
43     std::shared_lock<std::shared_mutex> lock(mutex_);
44     if (resultSet_ == nullptr) {
45         return NativeRdb::E_ALREADY_CLOSED;
46     }
47     columnNames = colNames_;
48     return NativeRdb::E_OK;
49 }
50 
GetColumnCount(int &count)51 int RdbResultSetImpl::GetColumnCount(int &count)
52 {
53     std::shared_lock<std::shared_mutex> lock(mutex_);
54     if (resultSet_ == nullptr) {
55         return NativeRdb::E_ALREADY_CLOSED;
56     }
57     count = static_cast<int>(colNames_.size());
58     return NativeRdb::E_OK;
59 }
60 
GetColumnType(int columnIndex, ColumnType &columnType)61 int RdbResultSetImpl::GetColumnType(int columnIndex, ColumnType &columnType)
62 {
63     std::shared_lock<std::shared_mutex> lock(mutex_);
64     if (resultSet_ == nullptr) {
65         return NativeRdb::E_ALREADY_CLOSED;
66     }
67     columnType = ConvertColumnType(resultSet_->GetColumnType(columnIndex));
68     return NativeRdb::E_OK;
69 }
70 
GetColumnIndex(const std::string &columnName, int &columnIndex)71 int RdbResultSetImpl::GetColumnIndex(const std::string &columnName, int &columnIndex)
72 {
73     std::shared_lock<std::shared_mutex> lock(mutex_);
74     if (resultSet_ == nullptr) {
75         return NativeRdb::E_ALREADY_CLOSED;
76     }
77     for (size_t i = 0; i < colNames_.size(); i++) {
78         if (colNames_[i] == columnName) {
79             columnIndex = static_cast<int>(i);
80             return NativeRdb::E_OK;
81         }
82     }
83     return NativeRdb::E_ERROR;
84 }
85 
GetColumnName(int columnIndex, std::string &columnName)86 int RdbResultSetImpl::GetColumnName(int columnIndex, std::string &columnName)
87 {
88     std::shared_lock<std::shared_mutex> lock(mutex_);
89     if (resultSet_ == nullptr) {
90         return NativeRdb::E_ALREADY_CLOSED;
91     }
92     if (colNames_.size() <= static_cast<uint32_t>(columnIndex) || columnIndex < 0) {
93         return NativeRdb::E_ERROR;
94     }
95     columnName = colNames_[columnIndex];
96     return NativeRdb::E_OK;
97 }
98 
GetRowCount(int &count)99 int RdbResultSetImpl::GetRowCount(int &count)
100 {
101     std::shared_lock<std::shared_mutex> lock(mutex_);
102     if (resultSet_ == nullptr) {
103         return NativeRdb::E_ALREADY_CLOSED;
104     }
105     count = count_;
106     return NativeRdb::E_OK;
107 }
108 
GetRowIndex(int &position) const109 int RdbResultSetImpl::GetRowIndex(int &position) const
110 {
111     std::shared_lock<std::shared_mutex> lock(mutex_);
112     if (resultSet_ == nullptr) {
113         return NativeRdb::E_ALREADY_CLOSED;
114     }
115     position = current_;
116     return NativeRdb::E_OK;
117 }
118 
GoTo(int offset)119 int RdbResultSetImpl::GoTo(int offset)
120 {
121     int ret = NativeRdb::E_OK;
122     while (offset != 0 && ret == NativeRdb::E_OK) {
123         if (offset > 0) {
124             ret = GoToNextRow();
125             offset--;
126         } else {
127             ret = GoToPreviousRow();
128             offset++;
129         }
130     }
131     return ret;
132 }
133 
GoToRow(int position)134 int RdbResultSetImpl::GoToRow(int position)
135 {
136     return GoTo(position - current_);
137 }
138 
GoToFirstRow()139 int RdbResultSetImpl::GoToFirstRow()
140 {
141     std::unique_lock<std::shared_mutex> lock(mutex_);
142     if (resultSet_ == nullptr) {
143         return NativeRdb::E_ALREADY_CLOSED;
144     }
145     auto ret = resultSet_->MoveToFirst();
146     current_ = 0;
147     return ret == GeneralError::E_OK ?  NativeRdb::E_OK : NativeRdb::E_ERROR;
148 }
149 
GoToLastRow()150 int RdbResultSetImpl::GoToLastRow()
151 {
152     return GoToRow(count_ - 1);
153 }
154 
GoToNextRow()155 int RdbResultSetImpl::GoToNextRow()
156 {
157     std::unique_lock<std::shared_mutex> lock(mutex_);
158     if (resultSet_ == nullptr) {
159         return NativeRdb::E_ALREADY_CLOSED;
160     }
161     if (current_ >= count_ - 1) {
162         current_ = count_;
163         return NativeRdb::E_ERROR;
164     }
165 
166     auto ret = resultSet_->MoveToNext();
167     current_++;
168     return ret == GeneralError::E_OK ?  NativeRdb::E_OK : NativeRdb::E_ERROR;
169 }
170 
GoToPreviousRow()171 int RdbResultSetImpl::GoToPreviousRow()
172 {
173     std::unique_lock<std::shared_mutex> lock(mutex_);
174     if (resultSet_ == nullptr) {
175         return NativeRdb::E_ALREADY_CLOSED;
176     }
177     if (current_ <= 0) {
178         current_ = -1;
179         return NativeRdb::E_ERROR;
180     }
181 
182     auto ret = resultSet_->MoveToPrev();
183     current_--;
184     return ret == GeneralError::E_OK ?  NativeRdb::E_OK : NativeRdb::E_ERROR;
185 }
186 
IsEnded(bool &result)187 int RdbResultSetImpl::IsEnded(bool &result)
188 {
189     std::shared_lock<std::shared_mutex> lock(mutex_);
190     if (resultSet_ == nullptr) {
191         return NativeRdb::E_ALREADY_CLOSED;
192     }
193     result = current_ >= count_ || count_ <= 0;
194     return NativeRdb::E_OK;
195 }
196 
IsStarted(bool &result) const197 int RdbResultSetImpl::IsStarted(bool &result) const
198 {
199     std::shared_lock<std::shared_mutex> lock(mutex_);
200     if (resultSet_ == nullptr) {
201         return NativeRdb::E_ALREADY_CLOSED;
202     }
203     result = current_ < 0 || count_ <= 0;
204     return NativeRdb::E_OK;
205 }
206 
207 int RdbResultSetImpl::IsAtFirstRow(bool &result) const
208 {
209     std::shared_lock<std::shared_mutex> lock(mutex_);
210     if (resultSet_ == nullptr) {
211         return NativeRdb::E_ALREADY_CLOSED;
212     }
213     result = count_ > 0 && current_ == 0;
214     return NativeRdb::E_OK;
215 }
216 
217 int RdbResultSetImpl::IsAtLastRow(bool &result)
218 {
219     std::shared_lock<std::shared_mutex> lock(mutex_);
220     if (resultSet_ == nullptr) {
221         return NativeRdb::E_ALREADY_CLOSED;
222     }
223     result = count_ > 0 && current_ == count_ - 1;
224     return NativeRdb::E_OK;
225 }
226 
GetBlob(int columnIndex, std::vector<uint8_t> &value)227 int RdbResultSetImpl::GetBlob(int columnIndex, std::vector<uint8_t> &value)
228 {
229     std::shared_lock<std::shared_mutex> lock(mutex_);
230     if (resultSet_ == nullptr) {
231         return NativeRdb::E_ALREADY_CLOSED;
232     }
233     return Get(columnIndex, value);
234 }
235 
GetString(int columnIndex, std::string &value)236 int RdbResultSetImpl::GetString(int columnIndex, std::string &value)
237 {
238     std::shared_lock<std::shared_mutex> lock(mutex_);
239     if (resultSet_ == nullptr) {
240         return NativeRdb::E_ALREADY_CLOSED;
241     }
242     return Get(columnIndex, value);
243 }
244 
GetInt(int columnIndex, int &value)245 int RdbResultSetImpl::GetInt(int columnIndex, int &value)
246 {
247     int64_t tmpValue;
248     int status = GetLong(columnIndex, tmpValue);
249     if (status == NativeRdb::E_OK) {
250         if (tmpValue < INT32_MIN || tmpValue > INT32_MAX) {
251             ZLOGE("Get int value overflow.");
252             return NativeRdb::E_ERROR;
253         }
254         value = static_cast<int32_t>(tmpValue);
255     }
256     return status;
257 }
258 
GetLong(int columnIndex, int64_t &value)259 int RdbResultSetImpl::GetLong(int columnIndex, int64_t &value)
260 {
261     std::shared_lock<std::shared_mutex> lock(mutex_);
262     if (resultSet_ == nullptr) {
263         return NativeRdb::E_ALREADY_CLOSED;
264     }
265     return Get(columnIndex, value);
266 }
267 
GetDouble(int columnIndex, double &value)268 int RdbResultSetImpl::GetDouble(int columnIndex, double &value)
269 {
270     std::shared_lock<std::shared_mutex> lock(mutex_);
271     if (resultSet_ == nullptr) {
272         return NativeRdb::E_ALREADY_CLOSED;
273     }
274     return Get(columnIndex, value);
275 }
276 
IsColumnNull(int columnIndex, bool &isNull)277 int RdbResultSetImpl::IsColumnNull(int columnIndex, bool &isNull)
278 {
279     std::shared_lock<std::shared_mutex> lock(mutex_);
280     if (resultSet_ == nullptr) {
281         return NativeRdb::E_ALREADY_CLOSED;
282     }
283     DistributedData::Value var;
284     auto status = resultSet_->Get(columnIndex, var);
285     if (status != DistributedData::GeneralError::E_OK) {
286         return NativeRdb::E_ERROR;
287     }
288     isNull = var.index() == DistributedData::TYPE_INDEX<std::monostate>;
289     return NativeRdb::E_OK;
290 }
291 
IsClosed() const292 bool RdbResultSetImpl::IsClosed() const
293 {
294     std::shared_lock<std::shared_mutex> lock(mutex_);
295     return resultSet_ == nullptr;
296 }
297 
Close()298 int RdbResultSetImpl::Close()
299 {
300     std::unique_lock<std::shared_mutex> lock(mutex_);
301     if (resultSet_ == nullptr) {
302         ZLOGW("Result set has been closed.");
303         return NativeRdb::E_OK;
304     }
305     resultSet_->Close();
306     resultSet_ = nullptr;
307     return NativeRdb::E_OK;
308 }
309 
ConvertColumnType(int32_t columnType) const310 ColumnType RdbResultSetImpl::ConvertColumnType(int32_t columnType) const
311 {
312     if (static_cast<uint32_t>(columnType) >= DistributedData::TYPE_MAX || columnType < 0) {
313         return ColumnType::TYPE_NULL;
314     }
315     return COLUMNTYPES[columnType];
316 }
317 
GetAsset(int32_t col, NativeRdb::ValueObject::Asset& value)318 int RdbResultSetImpl::GetAsset(int32_t col, NativeRdb::ValueObject::Asset& value)
319 {
320     std::shared_lock<std::shared_mutex> lock(mutex_);
321     if (resultSet_ == nullptr) {
322         return NativeRdb::E_ALREADY_CLOSED;
323     }
324     return Get(col, value);
325 }
326 
GetAssets(int32_t col, NativeRdb::ValueObject::Assets& value)327 int RdbResultSetImpl::GetAssets(int32_t col, NativeRdb::ValueObject::Assets& value)
328 {
329     std::shared_lock<std::shared_mutex> lock(mutex_);
330     if (resultSet_ == nullptr) {
331         return NativeRdb::E_ALREADY_CLOSED;
332     }
333     return Get(col, value);
334 }
335 
GetFloat32Array(int32_t index, NativeRdb::ValueObject::FloatVector& vecs)336 int RdbResultSetImpl::GetFloat32Array(int32_t index, NativeRdb::ValueObject::FloatVector& vecs)
337 {
338     std::shared_lock<std::shared_mutex> lock(mutex_);
339     if (resultSet_ == nullptr) {
340         return NativeRdb::E_ALREADY_CLOSED;
341     }
342     return NativeRdb::E_NOT_SUPPORT;
343 }
344 
Get(int32_t col, NativeRdb::ValueObject& value)345 int RdbResultSetImpl::Get(int32_t col, NativeRdb::ValueObject& value)
346 {
347     std::shared_lock<std::shared_mutex> lock(mutex_);
348     if (resultSet_ == nullptr) {
349         return NativeRdb::E_ALREADY_CLOSED;
350     }
351     auto [errCode, object] = GetValue(col);
352     value = std::move(object);
353     return errCode;
354 }
355 
GetRow(NativeRdb::RowEntity& rowEntity)356 int RdbResultSetImpl::GetRow(NativeRdb::RowEntity& rowEntity)
357 {
358     return NativeRdb::E_NOT_SUPPORT;
359 }
360 
GetSize(int col, size_t& size)361 int RdbResultSetImpl::GetSize(int col, size_t& size)
362 {
363     std::shared_lock<std::shared_mutex> lock(mutex_);
364     if (resultSet_ == nullptr) {
365         return NativeRdb::E_ALREADY_CLOSED;
366     }
367     auto [errCode, value] = GetValue(col);
368     if (errCode != NativeRdb::E_OK) {
369         return errCode;
370     }
371     auto object = static_cast<ValueObject>(value);
372     if (object.GetType() == ValueObject::TYPE_STRING) {
373         auto val = std::get_if<std::string>(&object.value);
374         if (val != nullptr) {
375             size = val->size();
376         }
377     } else if (object.GetType() == ValueObject::TYPE_BLOB) {
378         auto val = std::get_if<std::vector<uint8_t>>(&object.value);
379         if (val != nullptr) {
380             size = val->size();
381         }
382     }
383     return NativeRdb::E_OK;
384 }
385 } // namespace OHOS::DistributedRdb
386