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 
16 #define LOG_TAG "AbsResultSet"
17 #include "abs_result_set.h"
18 
19 #include <algorithm>
20 #include <tuple>
21 #include <utility>
22 
23 #include "logger.h"
24 #include "rdb_errno.h"
25 #include "rdb_trace.h"
26 #include "result_set.h"
27 #include "sqlite_utils.h"
28 
29 namespace OHOS {
30 namespace NativeRdb {
31 using namespace OHOS::Rdb;
Put(const std::string & name,int32_t index,ValueObject && value)32 void RowEntity::Put(const std::string& name, int32_t index, ValueObject&& value)
33 {
34     if (index < 0 || index >= static_cast<int>(indexs_.size())) {
35         return ;
36     }
37     auto it = values_.emplace(name, std::move(value));
38     indexs_[index] = it.first;
39 }
40 
Get(const std::string & name) const41 ValueObject RowEntity::Get(const std::string &name) const
42 {
43     auto it = values_.find(name);
44     if (it == values_.end()) {
45         return ValueObject();
46     }
47     return it->second;
48 }
49 
Get(int index) const50 ValueObject RowEntity::Get(int index) const
51 {
52     if (index < 0 || index >= static_cast<int>(indexs_.size())) {
53         return ValueObject();
54     }
55     return indexs_[index]->second;
56 }
57 
Get() const58 const std::map<std::string, ValueObject> &RowEntity::Get() const
59 {
60     return values_;
61 }
62 
Steal()63 std::map<std::string, ValueObject> RowEntity::Steal()
64 {
65     indexs_.clear();
66     return std::move(values_);
67 }
68 
Clear(int32_t size)69 void RowEntity::Clear(int32_t size)
70 {
71     values_.clear();
72     indexs_.clear();
73     indexs_.resize(size);
74 }
75 
AbsResultSet()76 AbsResultSet::AbsResultSet()
77 {
78 }
79 
AbsResultSet(bool safe)80 AbsResultSet::AbsResultSet(bool safe) : globalMtx_(safe)
81 {
82 }
83 
~AbsResultSet()84 AbsResultSet::~AbsResultSet()
85 {
86     rowPos_ = INIT_POS;
87     isClosed_ = true;
88 }
89 
GetRowCount(int & count)90 int AbsResultSet::GetRowCount(int &count)
91 {
92     count = rowCount_;
93     if (lastErr_ != E_OK) {
94         LOG_ERROR("ResultSet has lastErr %{public}d", lastErr_);
95         return lastErr_;
96     }
97     if (rowCount_ != NO_COUNT) {
98         return E_OK;
99     }
100 
101     if (isClosed_) {
102         LOG_ERROR("fail, result set E_ALREADY_CLOSED.");
103         return E_ALREADY_CLOSED;
104     }
105 
106     return E_OK;
107 }
108 
GetAllColumnNames(std::vector<std::string> & columnNames)109 int AbsResultSet::GetAllColumnNames(std::vector<std::string> &columnNames)
110 {
111     int errCode = E_OK;
112     if (columnCount_ < 0) {
113         errCode = InitColumnNames();
114     }
115 
116     if (columnCount_ < 0) {
117         return errCode;
118     }
119     columnNames.resize(columnCount_);
120     for (auto &[name, index] : columnMap_) {
121         if (index > columnCount_) {
122             continue;
123         }
124         columnNames[index] = name;
125     }
126     return E_OK;
127 }
128 
InitColumnNames()129 int AbsResultSet::InitColumnNames()
130 {
131     if (isClosed_) {
132         return E_ALREADY_CLOSED;
133     }
134 
135     auto [errCode, names] = GetColumnNames();
136     if (errCode != E_OK) {
137         LOG_DEBUG("ret is %{public}d", errCode);
138         return errCode;
139     }
140 
141     std::lock_guard<decltype(globalMtx_)> lockGuard(globalMtx_);
142     if (columnCount_ >= 0) {
143         return E_OK;
144     }
145 
146     for (size_t i = 0; i < names.size(); ++i) {
147         columnMap_.insert(std::pair{names[i], i});
148     }
149     columnCount_ = static_cast<int>(names.size());
150     return E_OK;
151 }
152 
GetBlob(int columnIndex,std::vector<uint8_t> & blob)153 int AbsResultSet::GetBlob(int columnIndex, std::vector<uint8_t>& blob)
154 {
155     ValueObject object;
156     int errorCode = Get(columnIndex, object);
157     if (errorCode != E_OK) {
158         return errorCode;
159     }
160     blob = object;
161     int type = object.GetType();
162     if (type == ValueObject::TYPE_ASSETS || type == ValueObject::TYPE_ASSET || type == ValueObject::TYPE_BIGINT ||
163         type == ValueObject::TYPE_VECS) {
164         LOG_ERROR("type invalid col:%{public}d, type:%{public}d!", columnIndex, type);
165         return E_INVALID_OBJECT_TYPE;
166     }
167 
168     return E_OK;
169 }
170 
GetString(int columnIndex,std::string & value)171 int AbsResultSet::GetString(int columnIndex, std::string &value)
172 {
173     ValueObject object;
174     int errorCode = Get(columnIndex, object);
175     if (errorCode != E_OK) {
176         return errorCode;
177     }
178     value = static_cast<std::string>(object);
179     int type = object.GetType();
180     if (type == ValueObject::TYPE_ASSETS || type == ValueObject::TYPE_ASSET || type == ValueObject::TYPE_BIGINT ||
181         type == ValueObject::TYPE_VECS) {
182         LOG_ERROR("type invalid col:%{public}d, type:%{public}d!", columnIndex, type);
183         return E_INVALID_OBJECT_TYPE;
184     }
185     return E_OK;
186 }
187 
GetInt(int columnIndex,int & value)188 int AbsResultSet::GetInt(int columnIndex, int &value)
189 {
190     int64_t temp = 0;
191     int errCode = GetLong(columnIndex, temp);
192     if (errCode != E_OK) {
193         return errCode;
194     }
195     value = int32_t(temp);
196     return E_OK;
197 }
198 
GetLong(int columnIndex,int64_t & value)199 int AbsResultSet::GetLong(int columnIndex, int64_t& value)
200 {
201     ValueObject object;
202     int errorCode = Get(columnIndex, object);
203     if (errorCode != E_OK) {
204         return errorCode;
205     }
206     value = object;
207     int type = object.GetType();
208     if (type == ValueObject::TYPE_ASSETS || type == ValueObject::TYPE_ASSET || type == ValueObject::TYPE_BIGINT ||
209         type == ValueObject::TYPE_VECS) {
210         LOG_ERROR("type invalid col:%{public}d, type:%{public}d!", columnIndex, type);
211         return E_INVALID_OBJECT_TYPE;
212     }
213     return E_OK;
214 }
215 
GetDouble(int columnIndex,double & value)216 int AbsResultSet::GetDouble(int columnIndex, double& value)
217 {
218     ValueObject object;
219     int errorCode = Get(columnIndex, object);
220     if (errorCode != E_OK) {
221         return errorCode;
222     }
223     value = object;
224     int type = object.GetType();
225     if (type == ValueObject::TYPE_ASSETS || type == ValueObject::TYPE_ASSET || type == ValueObject::TYPE_BIGINT ||
226         type == ValueObject::TYPE_VECS) {
227         LOG_ERROR("type invalid col:%{public}d, type:%{public}d!", columnIndex, type);
228         return E_INVALID_OBJECT_TYPE;
229     }
230     return E_OK;
231 }
232 
IsColumnNull(int columnIndex,bool & isNull)233 int AbsResultSet::IsColumnNull(int columnIndex, bool &isNull)
234 {
235     if (lastErr_ != E_OK) {
236         return lastErr_;
237     }
238     ColumnType columnType = ColumnType::TYPE_NULL;
239     int errCode = GetColumnType(columnIndex, columnType);
240     if (errCode != E_OK) {
241         LOG_ERROR("ret is %{public}d", errCode);
242         return errCode;
243     }
244     isNull = (columnType == ColumnType::TYPE_NULL);
245     return E_OK;
246 }
247 
GetRow(RowEntity & rowEntity)248 int AbsResultSet::GetRow(RowEntity &rowEntity)
249 {
250     int errCode = E_OK;
251     if (columnCount_ < 0) {
252         errCode = InitColumnNames();
253     }
254 
255     if (columnCount_ < 0) {
256         return errCode;
257     }
258     rowEntity.Clear(columnCount_);
259     for (auto &[name, index] : columnMap_) {
260         ValueObject value;
261         auto ret = Get(index, value);
262         if (ret != E_OK) {
263             LOG_ERROR("Get(%{public}d, %{public}s)->ret %{public}d", index, SqliteUtils::Anonymous(name).c_str(), ret);
264             return ret;
265         }
266         rowEntity.Put(name, index, std::move(value));
267     }
268     return E_OK;
269 }
270 
GoToRow(int position)271 int AbsResultSet::GoToRow(int position)
272 {
273     return E_OK;
274 }
275 
GetColumnType(int columnIndex,ColumnType & columnType)276 int AbsResultSet::GetColumnType(int columnIndex, ColumnType &columnType)
277 {
278     return E_OK;
279 }
280 
GetRowIndex(int & position) const281 int AbsResultSet::GetRowIndex(int &position) const
282 {
283     position = rowPos_;
284     return E_OK;
285 }
286 
GoTo(int offset)287 int AbsResultSet::GoTo(int offset)
288 {
289     return GoToRow(rowPos_ + offset);
290 }
291 
GoToFirstRow()292 int AbsResultSet::GoToFirstRow()
293 {
294     return GoToRow(0);
295 }
296 
GoToLastRow()297 int AbsResultSet::GoToLastRow()
298 {
299     int rowCnt = 0;
300     int ret = GetRowCount(rowCnt);
301     if (ret != E_OK) {
302         LOG_ERROR("Failed to GetRowCount, ret is %{public}d", ret);
303         return ret;
304     }
305     if (rowCnt == 0) {
306         return E_ERROR;
307     }
308 
309     return GoToRow(rowCnt - 1);
310 }
311 
GoToNextRow()312 int AbsResultSet::GoToNextRow()
313 {
314     return GoToRow(rowPos_ + 1);
315 }
316 
GoToPreviousRow()317 int AbsResultSet::GoToPreviousRow()
318 {
319     return GoToRow(rowPos_ - 1);
320 }
321 
IsAtFirstRow(bool & result) const322 int AbsResultSet::IsAtFirstRow(bool &result) const
323 {
324     result = (rowPos_ == 0);
325     return E_OK;
326 }
327 
IsAtLastRow(bool & result)328 int AbsResultSet::IsAtLastRow(bool &result)
329 {
330     int rowCnt = 0;
331     int ret = GetRowCount(rowCnt);
332     if (ret != E_OK) {
333         LOG_ERROR("Failed to GetRowCount, ret is %{public}d", ret);
334         return ret;
335     }
336     result = (rowPos_ == (rowCnt - 1));
337     return E_OK;
338 }
339 
IsStarted(bool & result) const340 int AbsResultSet::IsStarted(bool &result) const
341 {
342     result = (rowPos_ != INIT_POS);
343     return E_OK;
344 }
345 
IsEnded()346 std::pair<int, bool> AbsResultSet::IsEnded()
347 {
348     int rowCnt = 0;
349     int ret = GetRowCount(rowCnt);
350     if (ret != E_OK) {
351         LOG_ERROR("Failed to GetRowCount, ret is %{public}d", ret);
352         return { ret, true };
353     }
354     return { E_OK, (rowCnt == 0) || (rowPos_ == rowCnt) };
355 }
356 
IsEnded(bool & result)357 int AbsResultSet::IsEnded(bool &result)
358 {
359     int res = E_OK;
360     std::tie(res, result) = IsEnded();
361     return res;
362 }
363 
GetColumnCount(int & count)364 int AbsResultSet::GetColumnCount(int &count)
365 {
366     if (columnCount_ >= 0) {
367         count = columnCount_;
368         return E_OK;
369     }
370     auto errCode = InitColumnNames();
371     if (errCode != E_OK) {
372         LOG_DEBUG("ret is %{public}d", errCode);
373         return errCode;
374     }
375     count = columnCount_;
376     return E_OK;
377 }
378 
GetColumnIndex(const std::string & columnName,int & columnIndex)379 int AbsResultSet::GetColumnIndex(const std::string &columnName, int &columnIndex)
380 {
381     columnIndex = -1;
382     int errCode = E_OK;
383     if (columnCount_ < 0) {
384         errCode = InitColumnNames();
385     }
386     if (columnCount_ < 0) {
387         return errCode;
388     }
389     auto it = columnMap_.find(columnName);
390     if (it != columnMap_.end()) {
391         columnIndex = it->second;
392         return E_OK;
393     }
394 
395     std::string lowerName = columnName;
396     SqliteUtils::Replace(lowerName, SqliteUtils::REP, "");
397     auto periodIndex = lowerName.rfind('.');
398     if (periodIndex != std::string::npos) {
399         lowerName = lowerName.substr(periodIndex + 1);
400     }
401     std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), ::tolower);
402     for (const auto& [name, index] : columnMap_) {
403         std::string temp = name;
404         std::transform(name.begin(), name.end(), temp.begin(), ::tolower);
405         if (lowerName == temp) {
406             columnIndex = index;
407             return E_OK;
408         }
409     }
410     LOG_ERROR("failed, columnName is: %{public}s", SqliteUtils::Anonymous(columnName).c_str());
411     return E_ERROR;
412 }
413 
GetColumnName(int columnIndex,std::string & columnName)414 int AbsResultSet::GetColumnName(int columnIndex, std::string &columnName)
415 {
416     int32_t errCode = 0;
417     if (columnCount_ < 0) {
418         errCode = InitColumnNames();
419     }
420     if (columnCount_ < 0) {
421         return errCode;
422     }
423     if (columnCount_ <= columnIndex || columnIndex < 0) {
424         LOG_ERROR("invalid columnIndex %{public}d", columnIndex);
425         return E_COLUMN_OUT_RANGE;
426     }
427 
428     for (const auto& [name, index] : columnMap_) {
429         if (index == columnIndex) {
430             columnName = name;
431             return E_OK;
432         }
433     }
434     return E_COLUMN_OUT_RANGE;
435 }
436 
IsClosed() const437 bool AbsResultSet::IsClosed() const
438 {
439     return isClosed_;
440 }
441 
Close()442 int AbsResultSet::Close()
443 {
444     // clear columnMap_
445     auto map = std::move(columnMap_);
446     isClosed_ = true;
447     rowPos_ = INIT_POS;
448     rowCount_ = NO_COUNT;
449     columnCount_ = -1;
450     return E_OK;
451 }
452 
GetAsset(int32_t col,ValueObject::Asset & value)453 int AbsResultSet::GetAsset(int32_t col, ValueObject::Asset &value)
454 {
455     ValueObject valueObject;
456     int errorCode = Get(col, valueObject);
457     if (errorCode != E_OK) {
458         return errorCode;
459     }
460 
461     if (valueObject.GetType() == ValueObject::TYPE_NULL) {
462         return E_NULL_OBJECT;
463     }
464 
465     if (valueObject.GetType() != ValueObject::TYPE_ASSET) {
466         LOG_ERROR("failed, type is %{public}d, col is %{public}d!", valueObject.GetType(), col);
467         return E_INVALID_OBJECT_TYPE;
468     }
469     value = valueObject;
470     return E_OK;
471 }
472 
GetAssets(int32_t col,ValueObject::Assets & value)473 int AbsResultSet::GetAssets(int32_t col, ValueObject::Assets &value)
474 {
475     ValueObject valueObject;
476     int errorCode = Get(col, valueObject);
477     if (errorCode != E_OK) {
478         return errorCode;
479     }
480 
481     if (valueObject.GetType() == ValueObject::TYPE_NULL) {
482         return E_NULL_OBJECT;
483     }
484 
485     if (valueObject.GetType() != ValueObject::TYPE_ASSETS) {
486         LOG_ERROR("failed, type is %{public}d, col is %{public}d!", valueObject.GetType(), col);
487         return E_INVALID_OBJECT_TYPE;
488     }
489     value = valueObject;
490     return E_OK;
491 }
492 
GetFloat32Array(int32_t col,ValueObject::FloatVector & value)493 int AbsResultSet::GetFloat32Array(int32_t col, ValueObject::FloatVector &value)
494 {
495     ValueObject valueObject;
496     int errorCode = Get(col, valueObject);
497     if (errorCode != E_OK) {
498         return errorCode;
499     }
500 
501     if (valueObject.GetType() == ValueObject::TYPE_NULL) {
502         return E_NULL_OBJECT;
503     }
504 
505     if (valueObject.GetType() != ValueObject::TYPE_VECS) {
506         LOG_ERROR("failed, type is %{public}d, col is %{public}d!", valueObject.GetType(), col);
507         return E_INVALID_OBJECT_TYPE;
508     }
509     value = valueObject;
510     return E_OK;
511 }
GetColumnNames()512 std::pair<int, std::vector<std::string>> AbsResultSet::GetColumnNames()
513 {
514     return { E_NOT_SUPPORT, {} };
515 }
516 } // namespace NativeRdb
517 } // namespace OHOS