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