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