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