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 "ResultSetProxy"
16 #include "result_set_proxy.h"
17 
18 #include "itypes_util.h"
19 #include "logger.h"
20 #include "message_parcel.h"
21 #include "rdb_errno.h"
22 
23 namespace OHOS::NativeRdb {
24 using namespace OHOS::Rdb;
25 using Code = RemoteResultSet::Code;
26 
ResultSetProxy(const sptr<IRemoteObject> & impl)27 ResultSetProxy::ResultSetProxy(const sptr<IRemoteObject> &impl) : IRemoteProxy<IResultSet>(impl)
28 {
29     LOG_INFO("Init result set proxy.");
30     remote_ = Remote();
31 }
32 
~ResultSetProxy()33 ResultSetProxy::~ResultSetProxy()
34 {
35     LOG_INFO("Result set destroy, close result.");
36     Close();
37 }
38 
GetColumnCount(int & count)39 int ResultSetProxy::GetColumnCount(int &count)
40 {
41     return Send(Code::CMD_GET_COLUMN_COUNT, count);
42 }
43 
GetColumnType(int columnIndex,ColumnType & columnType)44 int ResultSetProxy::GetColumnType(int columnIndex, ColumnType &columnType)
45 {
46     MessageParcel reply;
47     int status = SendRequest(Code::CMD_GET_COLUMN_TYPE, reply, columnIndex);
48     if (status != E_OK) {
49         return status;
50     }
51     int32_t type;
52     if (!ITypesUtil::Unmarshal(reply, type)) {
53         return E_ERROR;
54     }
55     columnType = static_cast<ColumnType>(type);
56     return E_OK;
57 }
58 
GetRowCount(int & count)59 int ResultSetProxy::GetRowCount(int &count)
60 {
61     return Send(Code::CMD_GET_ROW_COUNT, count);
62 }
63 
GetRowIndex(int & position) const64 int ResultSetProxy::GetRowIndex(int &position) const
65 {
66     return Send(Code::CMD_GET_ROW_INDEX, position);
67 }
68 
GoTo(int offset)69 int ResultSetProxy::GoTo(int offset)
70 {
71     MessageParcel reply;
72     return SendRequest(Code::CMD_GO_TO, reply, offset);
73 }
74 
GoToRow(int position)75 int ResultSetProxy::GoToRow(int position)
76 {
77     MessageParcel reply;
78     return SendRequest(Code::CMD_GO_TO_ROW, reply, position);
79 }
80 
GoToFirstRow()81 int ResultSetProxy::GoToFirstRow()
82 {
83     return Send(Code::CMD_GO_TO_FIRST_ROW);
84 }
85 
GoToLastRow()86 int ResultSetProxy::GoToLastRow()
87 {
88     return Send(Code::CMD_GO_TO_LAST_ROW);
89 }
90 
GoToNextRow()91 int ResultSetProxy::GoToNextRow()
92 {
93     return Send(Code::CMD_GO_TO_NEXT_ROW);
94 }
95 
GoToPreviousRow()96 int ResultSetProxy::GoToPreviousRow()
97 {
98     return Send(Code::CMD_GO_TO_PREV_ROW);
99 }
100 
IsEnded(bool & result)101 int ResultSetProxy::IsEnded(bool &result)
102 {
103     return Send(Code::CMD_IS_ENDED_ROW, result);
104 }
105 
IsStarted(bool & result) const106 int ResultSetProxy::IsStarted(bool &result) const
107 {
108     return Send(Code::CMD_IS_STARTED_ROW, result);
109 }
110 
IsAtFirstRow(bool & result) const111 int ResultSetProxy::IsAtFirstRow(bool &result) const
112 {
113     return Send(Code::CMD_IS_AT_FIRST_ROW, result);
114 }
115 
IsAtLastRow(bool & result)116 int ResultSetProxy::IsAtLastRow(bool &result)
117 {
118     return Send(Code::CMD_IS_AT_LAST_ROW, result);
119 }
120 
Get(int32_t col,ValueObject & value)121 int ResultSetProxy::Get(int32_t col, ValueObject &value)
122 {
123     MessageParcel reply;
124     int status = SendRequest(Code::CMD_GET, reply, col);
125     if (status != E_OK) {
126         return status;
127     }
128 
129     if (!ITypesUtil::Unmarshal(reply, value.value)) {
130         return E_ERROR;
131     }
132     return E_OK;
133 }
134 
GetSize(int columnIndex,size_t & size)135 int ResultSetProxy::GetSize(int columnIndex, size_t &size)
136 {
137     MessageParcel reply;
138     int status = SendRequest(Code::CMD_GET_SIZE, reply, columnIndex);
139     if (status != E_OK) {
140         return status;
141     }
142     if (!ITypesUtil::Unmarshal(reply, size)) {
143         return E_ERROR;
144     }
145     return E_OK;
146 }
147 
Close()148 int ResultSetProxy::Close()
149 {
150     auto ret = Send(Code::CMD_CLOSE);
151     if (ret == E_OK) {
152         AbsResultSet::Close();
153     }
154     return ret;
155 }
156 
GetColumnNames()157 std::pair<int, std::vector<std::string>> ResultSetProxy::GetColumnNames()
158 {
159     std::vector<std::string> colNames;
160     auto status = Send(Code::CMD_GET_ALL_COLUMN_NAMES, colNames);
161     if (status != E_OK) {
162         LOG_ERROR("Reply error, status:%{public}d, code:%{public}d.", status, Code::CMD_GET_ALL_COLUMN_NAMES);
163         return { status, {} };
164     }
165     return { E_OK, std::move(colNames) };
166 }
167 
168 template<typename... T>
Send(uint32_t code,T &...output) const169 int ResultSetProxy::Send(uint32_t code, T &...output) const
170 {
171     MessageParcel reply;
172     auto status = SendRequest(code, reply);
173     if (status != E_OK) {
174         return status;
175     }
176     if (!ITypesUtil::Unmarshal(reply, output...)) {
177         LOG_ERROR("Unmarshal failed, code:%{public}d.", code);
178         return E_ERROR;
179     }
180     return E_OK;
181 }
182 
183 template<typename... T>
SendRequest(uint32_t code,MessageParcel & reply,const T &...input) const184 int ResultSetProxy::SendRequest(uint32_t code, MessageParcel &reply, const T &...input) const
185 {
186     if (remote_ == nullptr) {
187         LOG_ERROR("remote_ is null, code:%{public}d, input:%{public}zu.", code, sizeof...(input));
188         return E_ERROR;
189     }
190 
191     MessageParcel data;
192     if (!data.WriteInterfaceToken(ResultSetProxy::GetDescriptor())) {
193         LOG_ERROR("Write descriptor failed, code is %{public}d.", code);
194         return E_ERROR;
195     }
196 
197     if (!ITypesUtil::Marshal(data, input...)) {
198         LOG_ERROR("Marshal failed, code is %{public}d.", code);
199         return E_ERROR;
200     }
201 
202     if (!reply.SetMaxCapacity(MAX_IPC_CAPACITY)) {
203         LOG_ERROR("Set max capacity failed, code is %{public}d.", code);
204         return E_ERROR;
205     }
206 
207     MessageOption mo{ MessageOption::TF_SYNC };
208     int32_t status = remote_->SendRequest(code, data, reply, mo);
209     if (status != 0) {
210         LOG_ERROR("Send failed, error:%{public}d, code:%{public}d.", status, code);
211         return E_ERROR;
212     }
213     auto success = ITypesUtil::Unmarshal(reply, status);
214     if (status != E_OK || !success) {
215         LOG_ERROR("Reply failed, status:%{public}d, code:%{public}d.", status, code);
216         return E_ERROR;
217     }
218     return status;
219 }
220 } // namespace OHOS::NativeRdb