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 #define LOG_TAG "RdbResultSetBridge"
16 #include "rdb_result_set_bridge.h"
17 
18 #include "logger.h"
19 #include "rdb_errno.h"
20 #include "result_set.h"
21 #include "securec.h"
22 
23 namespace OHOS {
24 namespace RdbDataShareAdapter {
25 using namespace OHOS::Rdb;
26 using namespace OHOS::NativeRdb;
27 
RdbResultSetBridge(std::shared_ptr<ResultSet> resultSet)28 RdbResultSetBridge::RdbResultSetBridge(std::shared_ptr<ResultSet> resultSet) : rdbResultSet_(resultSet)
29 {
30 }
31 
~RdbResultSetBridge()32 RdbResultSetBridge::~RdbResultSetBridge()
33 {
34 }
35 
GetRowCount(int & count)36 int RdbResultSetBridge::GetRowCount(int &count)
37 {
38     return rdbResultSet_->GetRowCount(count);
39 }
40 
GetAllColumnNames(std::vector<std::string> & columnOrKeyNames)41 int RdbResultSetBridge::GetAllColumnNames(std::vector<std::string> &columnOrKeyNames)
42 {
43     return rdbResultSet_->GetAllColumnNames(columnOrKeyNames);
44 }
45 
OnGo(int32_t start,int32_t target,Writer & writer)46 int RdbResultSetBridge::OnGo(int32_t start, int32_t target, Writer &writer)
47 {
48     int rowCount;
49     rdbResultSet_->GetRowCount(rowCount);
50     if (start < 0 || target < 0 || target >= rowCount) {
51         LOG_ERROR("Invalid targetRowIndex: %{public}d.", rowCount);
52         return -1;
53     }
54 
55     int columnCount;
56     rdbResultSet_->GetColumnCount(columnCount);
57     if (columnCount <= 0) {
58         LOG_ERROR("Invalid columnCount: %{public}d.", columnCount);
59         return -1;
60     }
61     LOG_DEBUG("rowCount: %{public}d, columnCount: %{public}d.", rowCount, columnCount);
62 
63     bool bResultSet = false;
64     rdbResultSet_->IsStarted(bResultSet);
65     if (!bResultSet) {
66         rdbResultSet_->GoToFirstRow();
67     }
68 
69     int errCode = rdbResultSet_->GoToRow(start);
70     if (errCode) {
71         LOG_ERROR("Go to row %{public}d failed.", start);
72         return -1;
73     }
74 
75     return WriteBlock(start, target, columnCount, writer);
76 }
77 
WriteBlock(int32_t start,int32_t target,int columnCount,Writer & writer)78 int32_t RdbResultSetBridge::WriteBlock(int32_t start, int32_t target, int columnCount, Writer &writer)
79 {
80     int errCode = 0;
81     int row = start;
82 
83     while (!errCode && row <= target) {
84         int status = writer.AllocRow();
85         if (status != 0) {
86             LOG_ERROR("SharedBlock is full.");
87             return row - 1;
88         }
89 
90         WriteColumn(columnCount, writer, row);
91         row++;
92         errCode = rdbResultSet_->GoToNextRow();
93     }
94     return target;
95 }
96 
WriteColumn(int columnCount,Writer & writer,int row)97 void RdbResultSetBridge::WriteColumn(int columnCount, Writer &writer, int row)
98 {
99     for (int i = 0; i < columnCount; i++) {
100         ColumnType type;
101         rdbResultSet_->GetColumnType(i, type);
102         switch (type) {
103             case ColumnType::TYPE_INTEGER:
104                 int64_t value;
105                 rdbResultSet_->GetLong(i, value);
106                 if (writer.Write(i, value)) {
107                     LOG_DEBUG("WriteLong failed of row: %{public}d, column: %{public}d", row, i);
108                 }
109                 break;
110             case ColumnType::TYPE_FLOAT:
111                 double dValue;
112                 rdbResultSet_->GetDouble(i, dValue);
113                 if (writer.Write(i, dValue)) {
114                     LOG_DEBUG("WriteDouble failed of row: %{public}d, column: %{public}d", row, i);
115                 }
116                 break;
117             case ColumnType::TYPE_NULL:
118                 if (writer.Write(i)) {
119                     LOG_DEBUG("WriteNull failed of row: row: %{public}d, column: %{public}d", row, i);
120                 }
121                 break;
122             case ColumnType::TYPE_BLOB:
123                 if (WriteBlobData(i, writer)) {
124                     LOG_DEBUG("WriteBlob failed of row: %{public}d, column: %{public}d", row, i);
125                 }
126                 break;
127             default:
128                 std::string stringValue;
129                 rdbResultSet_->GetString(i, stringValue);
130                 if (writer.Write(i, stringValue.c_str(), stringValue.size() + 1)) {
131                     LOG_DEBUG("WriteString failed of row: %{public}d, column: %{public}d", row, i);
132                 }
133         }
134     }
135 }
136 
WriteBlobData(int column,Writer & writer)137 bool RdbResultSetBridge::WriteBlobData(int column, Writer &writer)
138 {
139     std::vector<uint8_t> blobValue;
140     rdbResultSet_->GetBlob(column, blobValue);
141     if (blobValue.empty()) {
142         return false;
143     }
144 
145     return writer.Write(column, &blobValue[0], blobValue.size() * sizeof(uint8_t));
146 }
147 } // namespace RdbDataShareAdapter
148 } // namespace OHOS
149