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
16 #include "datashare_result_set_proxy.h"
17
18 #include <functional>
19
20 #include "datashare_result_set.h"
21 #include "datashare_js_utils.h"
22 #include "string_ex.h"
23 #include "datashare_log.h"
24
25 namespace OHOS {
26 namespace DataShare {
27 constexpr int MAX_INPUT_COUNT = 10;
28 static napi_ref __thread ctorRef_ = nullptr;
NewInstance(napi_env env,std::shared_ptr<DataShareResultSet> resultSet)29 napi_value DataShareResultSetProxy::NewInstance(napi_env env, std::shared_ptr<DataShareResultSet> resultSet)
30 {
31 napi_value cons = GetConstructor(env);
32 if (cons == nullptr) {
33 LOG_ERROR("GetConstructor is nullptr!");
34 return nullptr;
35 }
36 napi_value instance;
37 napi_status status = napi_new_instance(env, cons, 0, nullptr, &instance);
38 if (status != napi_ok) {
39 LOG_ERROR("napi_new_instance failed! code:%{public}d!", status);
40 return nullptr;
41 }
42
43 DataShareResultSetProxy *proxy = nullptr;
44 status = napi_unwrap(env, instance, reinterpret_cast<void **>(&proxy));
45 if (proxy == nullptr) {
46 LOG_ERROR("native instance is nullptr! code:%{public}d!", status);
47 return instance;
48 }
49
50 *proxy = std::move(resultSet);
51 return instance;
52 }
53
GetNativeObject(napi_env const & env,napi_value const & arg)54 std::shared_ptr<DataShareResultSet> DataShareResultSetProxy::GetNativeObject(
55 napi_env const &env, napi_value const &arg)
56 {
57 if (arg == nullptr) {
58 LOG_ERROR("arg is null.");
59 return nullptr;
60 }
61 DataShareResultSetProxy *proxy = nullptr;
62 napi_unwrap(env, arg, reinterpret_cast<void **>(&proxy));
63 if (proxy == nullptr) {
64 LOG_ERROR("proxy is null.");
65 return nullptr;
66 }
67 return proxy->resultSet_;
68 }
69
GetConstructor(napi_env env)70 napi_value DataShareResultSetProxy::GetConstructor(napi_env env)
71 {
72 napi_value cons;
73 if (ctorRef_ != nullptr) {
74 NAPI_CALL(env, napi_get_reference_value(env, ctorRef_, &cons));
75 return cons;
76 }
77 LOG_INFO("Get DataShareResultSet constructor");
78 napi_property_descriptor clzDes[] = {
79 DECLARE_NAPI_FUNCTION("goToFirstRow", GoToFirstRow),
80 DECLARE_NAPI_FUNCTION("goToLastRow", GoToLastRow),
81 DECLARE_NAPI_FUNCTION("goToNextRow", GoToNextRow),
82 DECLARE_NAPI_FUNCTION("goToPreviousRow", GoToPreviousRow),
83 DECLARE_NAPI_FUNCTION("goTo", GoTo),
84 DECLARE_NAPI_FUNCTION("goToRow", GoToRow),
85 DECLARE_NAPI_FUNCTION("getBlob", GetBlob),
86 DECLARE_NAPI_FUNCTION("getString", GetString),
87 DECLARE_NAPI_FUNCTION("getLong", GetLong),
88 DECLARE_NAPI_FUNCTION("getDouble", GetDouble),
89 DECLARE_NAPI_FUNCTION("close", Close),
90 DECLARE_NAPI_FUNCTION("getColumnIndex", GetColumnIndex),
91 DECLARE_NAPI_FUNCTION("getColumnName", GetColumnName),
92 DECLARE_NAPI_FUNCTION("getDataType", GetDataType),
93
94 DECLARE_NAPI_GETTER("columnNames", GetAllColumnNames),
95 DECLARE_NAPI_GETTER("columnCount", GetColumnCount),
96 DECLARE_NAPI_GETTER("rowCount", GetRowCount),
97 DECLARE_NAPI_GETTER("isClosed", IsClosed),
98 };
99 NAPI_CALL(env, napi_define_class(env, "DataShareResultSet", NAPI_AUTO_LENGTH, Initialize, nullptr,
100 sizeof(clzDes) / sizeof(napi_property_descriptor), clzDes, &cons));
101 NAPI_CALL(env, napi_create_reference(env, cons, 1, &ctorRef_));
102 return cons;
103 }
104
Initialize(napi_env env,napi_callback_info info)105 napi_value DataShareResultSetProxy::Initialize(napi_env env, napi_callback_info info)
106 {
107 napi_value self = nullptr;
108 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &self, nullptr));
109 auto *proxy = new (std::nothrow) DataShareResultSetProxy();
110 if (proxy == nullptr) {
111 LOG_ERROR("DataShareResultSetProxy::Initialize new DataShareResultSetProxy error.");
112 return nullptr;
113 }
114 auto finalize = [](napi_env env, void *data, void *hint) {
115 DataShareResultSetProxy *proxy = reinterpret_cast<DataShareResultSetProxy *>(data);
116 if (proxy != nullptr) {
117 delete proxy;
118 }
119 };
120 napi_status status = napi_wrap(env, self, proxy, finalize, nullptr, nullptr);
121 if (status != napi_ok) {
122 LOG_ERROR("napi_wrap failed! code:%{public}d!", status);
123 finalize(env, proxy, nullptr);
124 return nullptr;
125 }
126 return self;
127 }
128
~DataShareResultSetProxy()129 DataShareResultSetProxy::~DataShareResultSetProxy()
130 {
131 LOG_DEBUG("DataShareResultSetProxy destructor!");
132 if (resultSet_ != nullptr && !resultSet_->IsClosed()) {
133 resultSet_->Close();
134 }
135 }
136
DataShareResultSetProxy(std::shared_ptr<DataShareResultSet> resultSet)137 DataShareResultSetProxy::DataShareResultSetProxy(std::shared_ptr<DataShareResultSet> resultSet)
138 {
139 if (resultSet_ == resultSet) {
140 return;
141 }
142 resultSet_ = std::move(resultSet);
143 }
144
operator =(std::shared_ptr<DataShareResultSet> resultSet)145 DataShareResultSetProxy &DataShareResultSetProxy::operator=(std::shared_ptr<DataShareResultSet> resultSet)
146 {
147 if (resultSet_ == resultSet) {
148 return *this;
149 }
150 resultSet_ = std::move(resultSet);
151 return *this;
152 }
153
GetInnerResultSet(napi_env env,napi_callback_info info)154 std::shared_ptr<DataShareResultSet> DataShareResultSetProxy::GetInnerResultSet(napi_env env,
155 napi_callback_info info)
156 {
157 DataShareResultSetProxy *resultSet = nullptr;
158 napi_value self = nullptr;
159 napi_get_cb_info(env, info, nullptr, nullptr, &self, nullptr);
160 napi_unwrap(env, self, reinterpret_cast<void **>(&resultSet));
161 return resultSet->resultSet_;
162 }
163
GoToFirstRow(napi_env env,napi_callback_info info)164 napi_value DataShareResultSetProxy::GoToFirstRow(napi_env env, napi_callback_info info)
165 {
166 int errCode = E_ERROR;
167 std::shared_ptr<DataShareResultSet> innerResultSet = GetInnerResultSet(env, info);
168 if (innerResultSet != nullptr) {
169 errCode = innerResultSet->GoToFirstRow();
170 if (errCode != E_OK) {
171 LOG_ERROR("failed code:%{public}d", errCode);
172 }
173 } else {
174 LOG_ERROR("GetInnerResultSet failed.");
175 }
176 return DataShareJSUtils::Convert2JSValue(env, (errCode == E_OK));
177 }
178
GoToLastRow(napi_env env,napi_callback_info info)179 napi_value DataShareResultSetProxy::GoToLastRow(napi_env env, napi_callback_info info)
180 {
181 int errCode = E_ERROR;
182 std::shared_ptr<DataShareResultSet> innerResultSet = GetInnerResultSet(env, info);
183 if (innerResultSet != nullptr) {
184 errCode = innerResultSet->GoToLastRow();
185 if (errCode != E_OK) {
186 LOG_ERROR("failed code:%{public}d", errCode);
187 }
188 } else {
189 LOG_ERROR("GetInnerResultSet failed.");
190 }
191 return DataShareJSUtils::Convert2JSValue(env, (errCode == E_OK));
192 }
193
GoToNextRow(napi_env env,napi_callback_info info)194 napi_value DataShareResultSetProxy::GoToNextRow(napi_env env, napi_callback_info info)
195 {
196 int errCode = E_ERROR;
197 std::shared_ptr<DataShareResultSet> innerResultSet = GetInnerResultSet(env, info);
198 if (innerResultSet != nullptr) {
199 errCode = innerResultSet->GoToNextRow();
200 if (errCode != E_OK) {
201 LOG_ERROR("failed code:%{public}d", errCode);
202 }
203 } else {
204 LOG_ERROR("GetInnerResultSet failed.");
205 }
206 return DataShareJSUtils::Convert2JSValue(env, (errCode == E_OK));
207 }
208
GoToPreviousRow(napi_env env,napi_callback_info info)209 napi_value DataShareResultSetProxy::GoToPreviousRow(napi_env env, napi_callback_info info)
210 {
211 int errCode = E_ERROR;
212 std::shared_ptr<DataShareResultSet> innerResultSet = GetInnerResultSet(env, info);
213 if (innerResultSet != nullptr) {
214 errCode = innerResultSet->GoToPreviousRow();
215 if (errCode != E_OK) {
216 LOG_ERROR("failed code:%{public}d", errCode);
217 }
218 } else {
219 LOG_ERROR("GetInnerResultSet failed.");
220 }
221 return DataShareJSUtils::Convert2JSValue(env, (errCode == E_OK));
222 }
223
GoTo(napi_env env,napi_callback_info info)224 napi_value DataShareResultSetProxy::GoTo(napi_env env, napi_callback_info info)
225 {
226 int32_t offset = -1;
227 size_t argc = MAX_INPUT_COUNT;
228 napi_value args[MAX_INPUT_COUNT] = { 0 };
229 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
230 NAPI_ASSERT(env, argc > 0, "Invalid argvs!");
231 NAPI_CALL(env, napi_get_value_int32(env, args[0], &offset));
232 int errCode = E_ERROR;
233 std::shared_ptr<DataShareResultSet> innerResultSet = GetInnerResultSet(env, info);
234 if (innerResultSet != nullptr) {
235 errCode = innerResultSet->GoTo(offset);
236 if (errCode != E_OK) {
237 LOG_ERROR("failed code:%{public}d", errCode);
238 }
239 } else {
240 LOG_ERROR("GetInnerResultSet failed.");
241 }
242 return DataShareJSUtils::Convert2JSValue(env, (errCode == E_OK));
243 }
244
GoToRow(napi_env env,napi_callback_info info)245 napi_value DataShareResultSetProxy::GoToRow(napi_env env, napi_callback_info info)
246 {
247 int32_t position = -1;
248 size_t argc = MAX_INPUT_COUNT;
249 napi_value args[MAX_INPUT_COUNT] = { 0 };
250 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
251 NAPI_ASSERT(env, argc > 0, "Invalid argvs!");
252 NAPI_CALL(env, napi_get_value_int32(env, args[0], &position));
253 int errCode = E_ERROR;
254 std::shared_ptr<DataShareResultSet> innerResultSet = GetInnerResultSet(env, info);
255 if (innerResultSet != nullptr) {
256 errCode = innerResultSet->GoToRow(position);
257 if (errCode != E_OK) {
258 LOG_ERROR("failed code:%{public}d", errCode);
259 }
260 } else {
261 LOG_ERROR("GetInnerResultSet failed.");
262 }
263 return DataShareJSUtils::Convert2JSValue(env, (errCode == E_OK));
264 }
265
GetBlob(napi_env env,napi_callback_info info)266 napi_value DataShareResultSetProxy::GetBlob(napi_env env, napi_callback_info info)
267 {
268 int32_t columnIndex = -1;
269 std::vector<uint8_t> blob;
270 size_t argc = MAX_INPUT_COUNT;
271 napi_value args[MAX_INPUT_COUNT] = { 0 };
272 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
273 NAPI_ASSERT(env, argc > 0, "Invalid argvs!");
274 NAPI_CALL(env, napi_get_value_int32(env, args[0], &columnIndex));
275 std::shared_ptr<DataShareResultSet> innerResultSet = GetInnerResultSet(env, info);
276 if (innerResultSet != nullptr) {
277 int errCode = innerResultSet->GetBlob(columnIndex, blob);
278 if (errCode != E_OK) {
279 LOG_ERROR("failed code:%{public}d", errCode);
280 }
281 } else {
282 LOG_ERROR("GetInnerResultSet failed.");
283 }
284 return DataShareJSUtils::Convert2JSValue(env, blob);
285 }
286
GetString(napi_env env,napi_callback_info info)287 napi_value DataShareResultSetProxy::GetString(napi_env env, napi_callback_info info)
288 {
289 int32_t columnIndex = -1;
290 std::string value;
291 size_t argc = MAX_INPUT_COUNT;
292 napi_value args[MAX_INPUT_COUNT] = { 0 };
293 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
294 NAPI_ASSERT(env, argc > 0, "Invalid argvs!");
295 NAPI_CALL(env, napi_get_value_int32(env, args[0], &columnIndex));
296 std::shared_ptr<DataShareResultSet> innerResultSet = GetInnerResultSet(env, info);
297 if (innerResultSet != nullptr) {
298 int errCode = innerResultSet->GetString(columnIndex, value);
299 if (errCode != E_OK) {
300 LOG_ERROR("failed code:%{public}d", errCode);
301 }
302 } else {
303 LOG_ERROR("GetInnerResultSet failed.");
304 }
305 return DataShareJSUtils::Convert2JSValue(env, value);
306 }
307
GetLong(napi_env env,napi_callback_info info)308 napi_value DataShareResultSetProxy::GetLong(napi_env env, napi_callback_info info)
309 {
310 int32_t columnIndex = -1;
311 int64_t value = -1;
312 size_t argc = MAX_INPUT_COUNT;
313 napi_value args[MAX_INPUT_COUNT] = { 0 };
314 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
315 NAPI_ASSERT(env, argc > 0, "Invalid argvs!");
316 NAPI_CALL(env, napi_get_value_int32(env, args[0], &columnIndex));
317 std::shared_ptr<DataShareResultSet> innerResultSet = GetInnerResultSet(env, info);
318 if (innerResultSet != nullptr) {
319 int errCode = innerResultSet->GetLong(columnIndex, value);
320 if (errCode != E_OK) {
321 LOG_ERROR("failed code:%{public}d", errCode);
322 }
323 } else {
324 LOG_ERROR("GetInnerResultSet failed.");
325 }
326 return DataShareJSUtils::Convert2JSValue(env, value);
327 }
328
GetDouble(napi_env env,napi_callback_info info)329 napi_value DataShareResultSetProxy::GetDouble(napi_env env, napi_callback_info info)
330 {
331 int32_t columnIndex = -1;
332 double value = 0.0;
333 size_t argc = MAX_INPUT_COUNT;
334 napi_value args[MAX_INPUT_COUNT] = { 0 };
335 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
336 NAPI_ASSERT(env, argc > 0, "Invalid argvs!");
337 NAPI_CALL(env, napi_get_value_int32(env, args[0], &columnIndex));
338 std::shared_ptr<DataShareResultSet> innerResultSet = GetInnerResultSet(env, info);
339 if (innerResultSet != nullptr) {
340 int errCode = innerResultSet->GetDouble(columnIndex, value);
341 if (errCode != E_OK) {
342 LOG_ERROR("failed code:%{public}d", errCode);
343 }
344 } else {
345 LOG_ERROR("GetInnerResultSet failed.");
346 }
347 return DataShareJSUtils::Convert2JSValue(env, value);
348 }
349
Close(napi_env env,napi_callback_info info)350 napi_value DataShareResultSetProxy::Close(napi_env env, napi_callback_info info)
351 {
352 int errCode = E_ERROR;
353 DataShareResultSetProxy *resultSet = nullptr;
354 napi_value self = nullptr;
355 napi_get_cb_info(env, info, nullptr, nullptr, &self, nullptr);
356 napi_unwrap(env, self, reinterpret_cast<void **>(&resultSet));
357 if (resultSet == nullptr) {
358 return DataShareJSUtils::Convert2JSValue(env, (errCode == E_OK));
359 }
360 auto innerResultSet = resultSet->resultSet_;
361 if (innerResultSet != nullptr) {
362 errCode = innerResultSet->Close();
363 if (errCode != E_OK) {
364 LOG_ERROR("failed code:%{public}d", errCode);
365 }
366 resultSet->resultSet_ = nullptr;
367 } else {
368 LOG_ERROR("GetInnerResultSet failed.");
369 }
370 return DataShareJSUtils::Convert2JSValue(env, (errCode == E_OK));
371 }
372
GetColumnIndex(napi_env env,napi_callback_info info)373 napi_value DataShareResultSetProxy::GetColumnIndex(napi_env env, napi_callback_info info)
374 {
375 int32_t columnIndex = -1;
376 size_t argc = MAX_INPUT_COUNT;
377 napi_value args[MAX_INPUT_COUNT] = { 0 };
378 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
379 NAPI_ASSERT(env, argc > 0, "Invalid argvs!");
380 std::string columnName = DataShareJSUtils::Convert2String(env, args[0], DataShareJSUtils::DEFAULT_BUF_SIZE);
381 std::shared_ptr<DataShareResultSet> innerResultSet = GetInnerResultSet(env, info);
382 if (innerResultSet != nullptr) {
383 int errCode = innerResultSet->GetColumnIndex(columnName, columnIndex);
384 if (errCode != E_OK) {
385 LOG_ERROR("failed code:%{public}d", errCode);
386 }
387 } else {
388 LOG_ERROR("GetInnerResultSet failed.");
389 }
390 return DataShareJSUtils::Convert2JSValue(env, columnIndex);
391 }
392
GetColumnName(napi_env env,napi_callback_info info)393 napi_value DataShareResultSetProxy::GetColumnName(napi_env env, napi_callback_info info)
394 {
395 int32_t columnIndex = -1;
396 std::string columnName;
397 size_t argc = MAX_INPUT_COUNT;
398 napi_value args[MAX_INPUT_COUNT] = { 0 };
399 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
400 NAPI_ASSERT(env, argc > 0, "Invalid argvs!");
401 NAPI_CALL(env, napi_get_value_int32(env, args[0], &columnIndex));
402 std::shared_ptr<DataShareResultSet> innerResultSet = GetInnerResultSet(env, info);
403 if (innerResultSet != nullptr) {
404 int errCode = innerResultSet->GetColumnName(columnIndex, columnName);
405 if (errCode != E_OK) {
406 LOG_ERROR("failed code:%{public}d", errCode);
407 }
408 } else {
409 LOG_ERROR("GetInnerResultSet failed.");
410 }
411 return DataShareJSUtils::Convert2JSValue(env, columnName);
412 }
413
GetDataType(napi_env env,napi_callback_info info)414 napi_value DataShareResultSetProxy::GetDataType(napi_env env, napi_callback_info info)
415 {
416 int32_t columnIndex = -1;
417 DataType dataType = DataType::TYPE_NULL;
418 size_t argc = MAX_INPUT_COUNT;
419 napi_value args[MAX_INPUT_COUNT] = { 0 };
420 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
421 NAPI_ASSERT(env, argc > 0, "Invalid argvs!");
422 NAPI_CALL(env, napi_get_value_int32(env, args[0], &columnIndex));
423 std::shared_ptr<DataShareResultSet> innerResultSet = GetInnerResultSet(env, info);
424 if (innerResultSet != nullptr) {
425 int errCode = innerResultSet->GetDataType(columnIndex, dataType);
426 if (errCode != E_OK) {
427 LOG_ERROR("failed code:%{public}d", errCode);
428 }
429 } else {
430 LOG_ERROR("GetInnerResultSet failed.");
431 }
432 return DataShareJSUtils::Convert2JSValue(env, int32_t(dataType));
433 }
434
GetAllColumnNames(napi_env env,napi_callback_info info)435 napi_value DataShareResultSetProxy::GetAllColumnNames(napi_env env, napi_callback_info info)
436 {
437 std::vector<std::string> columnNames;
438 std::shared_ptr<DataShareResultSet> innerResultSet = GetInnerResultSet(env, info);
439 if (innerResultSet != nullptr) {
440 int errCode = innerResultSet->GetAllColumnNames(columnNames);
441 if (errCode != E_OK) {
442 LOG_ERROR("failed code:%{public}d", errCode);
443 }
444 } else {
445 LOG_ERROR("GetInnerResultSet failed.");
446 }
447 return DataShareJSUtils::Convert2JSValue(env, columnNames);
448 }
449
GetColumnCount(napi_env env,napi_callback_info info)450 napi_value DataShareResultSetProxy::GetColumnCount(napi_env env, napi_callback_info info)
451 {
452 int32_t count = -1;
453 std::shared_ptr<DataShareResultSet> innerResultSet = GetInnerResultSet(env, info);
454 if (innerResultSet != nullptr) {
455 int errCode = innerResultSet->GetColumnCount(count);
456 if (errCode != E_OK) {
457 LOG_ERROR("failed code:%{public}d", errCode);
458 }
459 } else {
460 LOG_ERROR("GetInnerResultSet failed.");
461 }
462 return DataShareJSUtils::Convert2JSValue(env, count);
463 }
464
GetRowCount(napi_env env,napi_callback_info info)465 napi_value DataShareResultSetProxy::GetRowCount(napi_env env, napi_callback_info info)
466 {
467 int32_t count = -1;
468 std::shared_ptr<DataShareResultSet> innerResultSet = GetInnerResultSet(env, info);
469 if (innerResultSet != nullptr) {
470 int errCode = innerResultSet->GetRowCount(count);
471 if (errCode != E_OK) {
472 LOG_ERROR("failed code:%{public}d", errCode);
473 }
474 } else {
475 LOG_ERROR("GetInnerResultSet failed.");
476 }
477 return DataShareJSUtils::Convert2JSValue(env, count);
478 }
479
IsClosed(napi_env env,napi_callback_info info)480 napi_value DataShareResultSetProxy::IsClosed(napi_env env, napi_callback_info info)
481 {
482 bool result = false;
483 std::shared_ptr<DataShareResultSet> innerResultSet = GetInnerResultSet(env, info);
484 if (innerResultSet != nullptr) {
485 result = innerResultSet->IsClosed();
486 } else {
487 LOG_ERROR("GetInnerResultSet failed.");
488 }
489 napi_value output;
490 napi_get_boolean(env, result, &output);
491 return output;
492 }
493 } // namespace DataShare
494 } // namespace OHOS
495