1 /*
2  * Copyright (c) 2024 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 #include "relational_store_impl_resultsetproxy.h"
17 #include "relational_store_utils.h"
18 #include "napi_rdb_error.h"
19 #include "value_object.h"
20 #include "native_log.h"
21 
22 namespace OHOS {
23 namespace Relational {
24     static const int E_OK = 0;
25 
ResultSetImpl(std::shared_ptr<NativeRdb::ResultSet> resultSet)26     ResultSetImpl::ResultSetImpl(std::shared_ptr<NativeRdb::ResultSet> resultSet)
27     {
28         resultSetValue = resultSet;
29     }
30 
GetClassType()31     OHOS::FFI::RuntimeType* ResultSetImpl::GetClassType()
32     {
33         static OHOS::FFI::RuntimeType runtimeType = OHOS::FFI::RuntimeType::Create<OHOS::FFI::FFIData>("ResultSetImpl");
34         return &runtimeType;
35     }
36 
GetAllColumnNames()37     CArrStr ResultSetImpl::GetAllColumnNames()
38     {
39         std::vector<std::string> colNames;
40         int errCode = resultSetValue->GetAllColumnNames(colNames);
41         if (errCode != RelationalStoreJsKit::OK) {
42             LOGE("GetAllColumnNames failed code: %{public}d", errCode);
43             return CArrStr{nullptr, 0};
44         }
45         if (colNames.size() == 0) {
46             return CArrStr{nullptr, 0};
47         }
48         char** result = static_cast<char**>(malloc(colNames.size() * sizeof(char*)));
49         if (result == nullptr) {
50             return CArrStr{nullptr, -1};
51         }
52         for (size_t i = 0; i < colNames.size(); i++) {
53             result[i] = MallocCString(colNames[i]);
54             if (result[i] == nullptr) {
55                 for (size_t j = 0; j < i; j++) {
56                     free(result[j]);
57                 }
58                 free(result);
59                 return CArrStr{nullptr, -1};
60             }
61         }
62         return CArrStr{result, int64_t(colNames.size())};
63     }
64 
GetColumnCount()65     int32_t ResultSetImpl::GetColumnCount()
66     {
67         int32_t count = 0;
68         int errCode = resultSetValue->GetColumnCount(count);
69         if (errCode != RelationalStoreJsKit::OK) {
70             LOGE("GetColumnCount failed code:%{public}d", errCode);
71         }
72         return count;
73     }
74 
GetRowCount()75     int32_t ResultSetImpl::GetRowCount()
76     {
77         int32_t result;
78         int errCode = resultSetValue->GetRowCount(result);
79         if (errCode != RelationalStoreJsKit::OK) {
80             LOGE("GetRowCount failed code:%{public}d", errCode);
81         }
82         return result;
83     }
84 
GetRowIndex()85     int32_t ResultSetImpl::GetRowIndex()
86     {
87         int32_t result;
88         int errCode = resultSetValue->GetRowIndex(result);
89         if (errCode != RelationalStoreJsKit::OK) {
90             LOGE("GetRowIndex failed code:%{public}d", errCode);
91         }
92         return result;
93     }
94 
IsAtFirstRow()95     bool ResultSetImpl::IsAtFirstRow()
96     {
97         bool result = false;
98         int errCode = resultSetValue->IsAtFirstRow(result);
99         if (errCode != RelationalStoreJsKit::OK) {
100             LOGE("IsAtFirstRow failed code:%{public}d", errCode);
101         }
102         return result;
103     }
104 
IsAtLastRow()105     bool ResultSetImpl::IsAtLastRow()
106     {
107         bool result = false;
108         int errCode = resultSetValue->IsAtLastRow(result);
109         if (errCode != RelationalStoreJsKit::OK) {
110             LOGE("IsAtLastRow failed code:%{public}d", errCode);
111         }
112         return result;
113     }
114 
IsEnded()115     bool ResultSetImpl::IsEnded()
116     {
117         bool result = false;
118         int errCode = resultSetValue->IsEnded(result);
119         if (errCode != RelationalStoreJsKit::OK) {
120             LOGE("IsEnded failed code:%{public}d", errCode);
121             result = true;
122         }
123         return result;
124     }
125 
IsStarted()126     bool ResultSetImpl::IsStarted()
127     {
128         bool result = false;
129         int errCode = resultSetValue->IsStarted(result);
130         if (errCode != RelationalStoreJsKit::OK) {
131             LOGE("IsBegin failed code:%{public}d", errCode);
132         }
133         return result;
134     }
135 
IsClosed()136     bool ResultSetImpl::IsClosed()
137     {
138         return resultSetValue->IsClosed();
139     }
140 
GetDouble(int32_t columnIndex,int32_t * rtnCode)141     double ResultSetImpl::GetDouble(int32_t columnIndex, int32_t* rtnCode)
142     {
143         double result = 0.0;
144         *rtnCode = resultSetValue->GetDouble(columnIndex, result);
145         return result;
146     }
147 
GoToRow(int32_t position,int32_t * rtnCode)148     bool ResultSetImpl::GoToRow(int32_t position, int32_t* rtnCode)
149     {
150         *rtnCode = resultSetValue->GoToRow(position);
151         return *rtnCode == RelationalStoreJsKit::OK;
152     }
153 
GoToPreviousRow(int32_t * rtnCode)154     bool ResultSetImpl::GoToPreviousRow(int32_t* rtnCode)
155     {
156         *rtnCode = resultSetValue->GoToPreviousRow();
157         return *rtnCode == RelationalStoreJsKit::OK;
158     }
159 
GoToLastRow(int32_t * rtnCode)160     bool ResultSetImpl::GoToLastRow(int32_t* rtnCode)
161     {
162         *rtnCode = resultSetValue->GoToLastRow();
163         return *rtnCode == RelationalStoreJsKit::OK;
164     }
165 
GetColumnName(int32_t columnIndex,int32_t * rtnCode)166     char* ResultSetImpl::GetColumnName(int32_t columnIndex, int32_t* rtnCode)
167     {
168         std::string result;
169         *rtnCode = resultSetValue->GetColumnName(columnIndex, result);
170         if (*rtnCode != RelationalStoreJsKit::OK) {
171             LOGE("IsAtLastRow failed code:%{public}d", *rtnCode);
172         }
173         return MallocCString(result);
174     }
175 
IsColumnNull(int32_t columnIndex,int32_t * rtnCode)176     bool ResultSetImpl::IsColumnNull(int32_t columnIndex, int32_t* rtnCode)
177     {
178         bool result;
179         *rtnCode = resultSetValue->IsColumnNull(columnIndex, result);
180         return result;
181     }
182 
GetAsset(int32_t columnIndex,int32_t * rtnCode)183     Asset ResultSetImpl::GetAsset(int32_t columnIndex, int32_t* rtnCode)
184     {
185         NativeRdb::ValueObject::Asset asset;
186         *rtnCode = resultSetValue->GetAsset(columnIndex, asset);
187         if (*rtnCode != RelationalStoreJsKit::OK) {
188             return Asset{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, 0};
189         }
190         Asset result = {
191             .name= MallocCString(asset.name),
192             .uri= MallocCString(asset.uri),
193             .path= MallocCString(asset.path),
194             .createTime= MallocCString(asset.createTime),
195             .modifyTime= MallocCString(asset.modifyTime),
196             .size= MallocCString(asset.size),
197             .status= (int32_t)asset.status
198         };
199         return result;
200     }
201 
Close()202     int32_t ResultSetImpl::Close()
203     {
204         return resultSetValue->Close();
205     }
206 
GetColumnIndex(char * columnName,int32_t * rtnCode)207     int32_t ResultSetImpl::GetColumnIndex(char* columnName, int32_t* rtnCode)
208     {
209         int32_t result;
210         *rtnCode = resultSetValue->GetColumnIndex(columnName, result);
211         return result;
212     }
213 
GetString(int32_t columnIndex,int32_t * rtnCode)214     char* ResultSetImpl::GetString(int32_t columnIndex, int32_t* rtnCode)
215     {
216         std::string result;
217         *rtnCode = resultSetValue->GetString(columnIndex, result);
218         return MallocCString(result);
219     }
220 
GoToFirstRow(int32_t * rtnCode)221     bool ResultSetImpl::GoToFirstRow(int32_t* rtnCode)
222     {
223         *rtnCode = resultSetValue->GoToFirstRow();
224         return *rtnCode == RelationalStoreJsKit::OK;
225     }
226 
GetLong(int32_t columnIndex,int32_t * rtnCode)227     int64_t ResultSetImpl::GetLong(int32_t columnIndex, int32_t* rtnCode)
228     {
229         int64_t result;
230         *rtnCode = resultSetValue->GetLong(columnIndex, result);
231         return result;
232     }
233 
GoToNextRow(int32_t * rtnCode)234     bool ResultSetImpl::GoToNextRow(int32_t* rtnCode)
235     {
236         *rtnCode = resultSetValue->GoToNextRow();
237         return *rtnCode == RelationalStoreJsKit::OK;
238     }
239 
GetBlob(int32_t columnIndex,int32_t * rtnCode)240     CArrUI8 ResultSetImpl::GetBlob(int32_t columnIndex, int32_t* rtnCode)
241     {
242         std::vector<uint8_t> vec;
243         *rtnCode = resultSetValue->GetBlob(columnIndex, vec);
244         if (*rtnCode != RelationalStoreJsKit::OK || vec.size() == 0) {
245             return CArrUI8{nullptr, 0};
246         }
247         uint8_t* result = static_cast<uint8_t*>(malloc(vec.size() * sizeof(uint8_t)));
248         if (result == nullptr) {
249             return CArrUI8{nullptr, -1};
250         }
251         for (size_t i = 0; i < vec.size(); i++) {
252             result[i] = vec[i];
253         }
254         return CArrUI8{result, int64_t(vec.size())};
255     }
256 
GoTo(int32_t offset,int32_t * rtnCode)257     bool ResultSetImpl::GoTo(int32_t offset, int32_t* rtnCode)
258     {
259         *rtnCode = resultSetValue->GoTo(offset);
260         return *rtnCode == RelationalStoreJsKit::OK;
261     }
262 
GetAssets(int32_t columnIndex,int32_t * rtnCode)263     Assets ResultSetImpl::GetAssets(int32_t columnIndex, int32_t* rtnCode)
264     {
265         std::vector<NativeRdb::ValueObject::Asset> assets;
266         *rtnCode = resultSetValue->GetAssets(columnIndex, assets);
267         if (*rtnCode != RelationalStoreJsKit::OK || assets.size() == 0) {
268             return Assets{nullptr, 0};
269         }
270         Asset* result = static_cast<Asset*>(malloc(assets.size() * sizeof(Asset)));
271         if (result == nullptr) {
272             return Assets{nullptr, -1};
273         }
274         for (size_t i = 0; i < assets.size(); i++) {
275             result[i] = Asset {
276                 .name= MallocCString(assets[i].name),
277                 .uri= MallocCString(assets[i].uri),
278                 .path= MallocCString(assets[i].path),
279                 .createTime= MallocCString(assets[i].createTime),
280                 .modifyTime= MallocCString(assets[i].modifyTime),
281                 .size= MallocCString(assets[i].size),
282                 .status= (int32_t)assets[i].status
283             };
284         }
285         return Assets{.head = result, .size = (int64_t)(assets.size())};
286     }
287 
GetRow(int32_t * rtnCode)288     ValuesBucket ResultSetImpl::GetRow(int32_t* rtnCode)
289     {
290         NativeRdb::RowEntity rowEntity;
291         *rtnCode = resultSetValue->GetRow(rowEntity);
292         if (*rtnCode != E_OK) {
293             return ValuesBucket{nullptr, nullptr, 0};
294         }
295         const std::map<std::string, NativeRdb::ValueObject> map = rowEntity.Get();
296         size_t size = map.size();
297         if (size == 0) {
298             return ValuesBucket{nullptr, nullptr, 0};
299         }
300         ValuesBucket result = ValuesBucket {
301             .key = static_cast<char**>(malloc(sizeof(char*) * size)),
302             .value = static_cast<ValueType*>(malloc(sizeof(ValueType) * size)),
303             .size = size
304         };
305         if (result.key == nullptr || result.value == nullptr) {
306             free(result.key);
307             free(result.value);
308             return ValuesBucket{nullptr, nullptr, -1};
309         }
310         int64_t i = 0;
311         for (auto &t : map) {
312             result.key[i] = MallocCString(t.first);
313             result.value[i] = ValueObjectToValueType(t.second);
314             i++;
315         }
316         return result;
317     }
318 }
319 }