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 "JsQuery"
16 #include "js_query.h"
17 #include "js_util.h"
18 #include "log_print.h"
19 #include "napi_queue.h"
20 #include "uv_queue.h"
21 
22 using namespace OHOS::DistributedKv;
23 
24 namespace OHOS::DistributedKVStore {
GetDataQuery() const25 const DataQuery& JsQuery::GetDataQuery() const
26 {
27     return query_;
28 }
29 
Constructor(napi_env env)30 napi_value JsQuery::Constructor(napi_env env)
31 {
32     auto lambda = []() -> std::vector<napi_property_descriptor> {
33         std::vector<napi_property_descriptor> properties = {
34             DECLARE_NAPI_FUNCTION("reset", JsQuery::Reset),
35             DECLARE_NAPI_FUNCTION("equalTo", JsQuery::EqualTo),
36             DECLARE_NAPI_FUNCTION("notEqualTo", JsQuery::NotEqualTo),
37             DECLARE_NAPI_FUNCTION("greaterThan", JsQuery::GreaterThan),
38             DECLARE_NAPI_FUNCTION("lessThan", JsQuery::LessThan),
39             DECLARE_NAPI_FUNCTION("greaterThanOrEqualTo", JsQuery::GreaterThanOrEqualTo),
40             DECLARE_NAPI_FUNCTION("lessThanOrEqualTo", JsQuery::LessThanOrEqualTo),
41             DECLARE_NAPI_FUNCTION("isNull", JsQuery::IsNull),
42             DECLARE_NAPI_FUNCTION("inNumber", JsQuery::InNumber),
43             DECLARE_NAPI_FUNCTION("inString", JsQuery::InString),
44             DECLARE_NAPI_FUNCTION("notInNumber", JsQuery::NotInNumber),
45             DECLARE_NAPI_FUNCTION("notInString", JsQuery::NotInString),
46             DECLARE_NAPI_FUNCTION("like", JsQuery::Like),
47             DECLARE_NAPI_FUNCTION("unlike", JsQuery::Unlike),
48             DECLARE_NAPI_FUNCTION("and", JsQuery::And),
49             DECLARE_NAPI_FUNCTION("or", JsQuery::Or),
50             DECLARE_NAPI_FUNCTION("orderByAsc", JsQuery::OrderByAsc),
51             DECLARE_NAPI_FUNCTION("orderByDesc", JsQuery::OrderByDesc),
52             DECLARE_NAPI_FUNCTION("limit", JsQuery::Limit),
53             DECLARE_NAPI_FUNCTION("isNotNull", JsQuery::IsNotNull),
54             DECLARE_NAPI_FUNCTION("beginGroup", JsQuery::BeginGroup),
55             DECLARE_NAPI_FUNCTION("endGroup", JsQuery::EndGroup),
56             DECLARE_NAPI_FUNCTION("prefixKey", JsQuery::PrefixKey),
57             DECLARE_NAPI_FUNCTION("setSuggestIndex", JsQuery::SetSuggestIndex),
58             DECLARE_NAPI_FUNCTION("deviceId", JsQuery::DeviceId),
59             DECLARE_NAPI_FUNCTION("getSqlLike", JsQuery::GetSqlLike),
60         };
61         return properties;
62     };
63     return JSUtil::DefineClass(env, "ohos.data.distributedKVStore", "Query", lambda, JsQuery::New);
64 }
65 
66 /*
67  * [JS API Prototype]
68  *      var query = new ddm.JsQuery();
69  */
New(napi_env env,napi_callback_info info)70 napi_value JsQuery::New(napi_env env, napi_callback_info info)
71 {
72     auto ctxt = std::make_shared<ContextBase>();
73     ctxt->GetCbInfoSync(env, info);
74     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
75         "Parameter error:param query must be object");
76 
77     JsQuery* query = new (std::nothrow) JsQuery();
78     ASSERT_ERR(env, query != nullptr, Status::INVALID_ARGUMENT,
79         "Parameter error:query is null");
80 
81     auto finalize = [](napi_env env, void* data, void* hint) {
82         ZLOGD("query finalize.");
83         auto* query = reinterpret_cast<JsQuery*>(data);
84         ASSERT_VOID(query != nullptr, "query is null!");
85         delete query;
86     };
87     ASSERT_CALL(env, napi_wrap(env, ctxt->self, query, finalize, nullptr, nullptr), query);
88     return ctxt->self;
89 }
90 
Reset(napi_env env,napi_callback_info info)91 napi_value JsQuery::Reset(napi_env env, napi_callback_info info)
92 {
93     auto ctxt = std::make_shared<ContextBase>();
94     ctxt->GetCbInfoSync(env, info);
95     NAPI_ASSERT(env, ctxt->status == napi_ok, "Reset error");
96 
97     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
98     query.Reset();
99     return ctxt->self;
100 }
101 
102 struct ValueContext : public ContextBase {
103     std::string field;
104     JSUtil::QueryVariant vv;
105 
GetValueSyncOHOS::DistributedKVStore::ValueContext106     void GetValueSync(napi_env env, napi_callback_info info)
107     {
108         auto input = [this, env](size_t argc, napi_value* argv) {
109             // required 2 arguments :: <field> <value>
110             ASSERT_BUSINESS_ERR(this, argc >= 2, Status::INVALID_ARGUMENT,
111                 "Parameter error:Mandatory parameters are left unspecified");
112             status = JSUtil::GetValue(env, argv[0], field);
113             ASSERT_BUSINESS_ERR(this, status == napi_ok, Status::INVALID_ARGUMENT,
114                 "Parameter error:parameter field type must be string");
115             status = JSUtil::GetValue(env, argv[1], vv);
116             ASSERT_BUSINESS_ERR(this, status == napi_ok, Status::INVALID_ARGUMENT,
117                 "Parameter error:parameter value type must be object");
118         };
119         GetCbInfoSync(env, info, input);
120     }
121 };
122 
123 /* [js] equalTo(field:string, value:number|string|boolean):JsQuery */
EqualTo(napi_env env,napi_callback_info info)124 napi_value JsQuery::EqualTo(napi_env env, napi_callback_info info)
125 {
126     ZLOGD("Query::EqualTo()");
127     auto ctxt = std::make_shared<ValueContext>();
128     ctxt->GetValueSync(env, info);
129     if (ctxt->isThrowError) {
130         ZLOGE("EqualTo exit");
131         return nullptr;
132     }
133     ASSERT_NULL(!ctxt->isThrowError, "EqualTo exit");
134     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
135         "Parameter error:equalto params must belong one of string boolean number");
136 
137     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
138     auto strValue = std::get_if<std::string>(&ctxt->vv);
139     if (strValue != nullptr) {
140         query.EqualTo(ctxt->field, *strValue);
141     } else {
142         auto boolValue = std::get_if<bool>(&ctxt->vv);
143         if (boolValue != nullptr) {
144             query.EqualTo(ctxt->field, *boolValue);
145         } else {
146             auto dblValue = std::get_if<double>(&ctxt->vv);
147             if (dblValue != nullptr) {
148                 query.EqualTo(ctxt->field, *dblValue);
149             }
150         }
151     }
152     return ctxt->self;
153 }
154 
NotEqualTo(napi_env env,napi_callback_info info)155 napi_value JsQuery::NotEqualTo(napi_env env, napi_callback_info info)
156 {
157     ZLOGD("Query::NotEqualTo()");
158     auto ctxt = std::make_shared<ValueContext>();
159     ctxt->GetValueSync(env, info);
160     ASSERT_NULL(!ctxt->isThrowError, "NotEqualTo exit");
161     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
162         "Parameter error:NotEqualTo params must belong one of string boolean number");
163 
164     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
165     auto strValue = std::get_if<std::string>(&ctxt->vv);
166     if (strValue != nullptr) {
167         query.NotEqualTo(ctxt->field, *strValue);
168     } else {
169         auto boolValue = std::get_if<bool>(&ctxt->vv);
170         if (boolValue != nullptr) {
171             query.NotEqualTo(ctxt->field, *boolValue);
172         } else {
173             auto dblValue = std::get_if<double>(&ctxt->vv);
174             if (dblValue != nullptr) {
175                 query.NotEqualTo(ctxt->field, *dblValue);
176             }
177         }
178     }
179     return ctxt->self;
180 }
181 
GreaterThan(napi_env env,napi_callback_info info)182 napi_value JsQuery::GreaterThan(napi_env env, napi_callback_info info)
183 {
184     ZLOGD("Query::GreaterThan()");
185     auto ctxt = std::make_shared<ValueContext>();
186     ctxt->GetValueSync(env, info);
187     ASSERT_NULL(!ctxt->isThrowError, "GreaterThan exit");
188     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
189         "The function GreaterThan params must belong one of string boolean number");
190 
191     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
192     auto strValue = std::get_if<std::string>(&ctxt->vv);
193     if (strValue != nullptr) {
194         query.GreaterThan(ctxt->field, *strValue);
195     } else {
196         auto boolValue = std::get_if<bool>(&ctxt->vv);
197         if (boolValue != nullptr) {
198             query.GreaterThan(ctxt->field, *boolValue);
199         } else {
200             auto dblValue = std::get_if<double>(&ctxt->vv);
201             if (dblValue != nullptr) {
202                 query.GreaterThan(ctxt->field, *dblValue);
203             }
204         }
205     }
206     return ctxt->self;
207 }
208 
LessThan(napi_env env,napi_callback_info info)209 napi_value JsQuery::LessThan(napi_env env, napi_callback_info info)
210 {
211     ZLOGD("Query::LessThan()");
212     auto ctxt = std::make_shared<ValueContext>();
213     ctxt->GetValueSync(env, info);
214     ASSERT_NULL(!ctxt->isThrowError, "LessThan exit");
215     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
216         "The parameter of the LessThan function must be a string or number.");
217 
218     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
219     auto strValue = std::get_if<std::string>(&ctxt->vv);
220     if (strValue != nullptr) {
221         query.LessThan(ctxt->field, *strValue);
222     } else {
223         auto boolValue = std::get_if<bool>(&ctxt->vv);
224         if (boolValue != nullptr) {
225             query.LessThan(ctxt->field, *boolValue);
226         } else {
227             auto dblValue = std::get_if<double>(&ctxt->vv);
228             if (dblValue != nullptr) {
229                 query.LessThan(ctxt->field, *dblValue);
230             }
231         }
232     }
233     return ctxt->self;
234 }
235 
GreaterThanOrEqualTo(napi_env env,napi_callback_info info)236 napi_value JsQuery::GreaterThanOrEqualTo(napi_env env, napi_callback_info info)
237 {
238     ZLOGD("Query::GreaterThanOrEqualTo()");
239     auto ctxt = std::make_shared<ValueContext>();
240     ctxt->GetValueSync(env, info);
241     ASSERT_NULL(!ctxt->isThrowError, "GreaterThanOrEqualTo exit");
242     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
243         "The function GreaterThanOrEqualTo params must belong one of string number");
244 
245     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
246     auto strValue = std::get_if<std::string>(&ctxt->vv);
247     if (strValue != nullptr) {
248         query.GreaterThanOrEqualTo(ctxt->field, *strValue);
249     } else {
250         auto boolValue = std::get_if<bool>(&ctxt->vv);
251         if (boolValue != nullptr) {
252             query.GreaterThanOrEqualTo(ctxt->field, *boolValue);
253         } else {
254             auto dblValue = std::get_if<double>(&ctxt->vv);
255             if (dblValue != nullptr) {
256                 query.GreaterThanOrEqualTo(ctxt->field, *dblValue);
257             }
258         }
259     }
260     return ctxt->self;
261 }
262 
LessThanOrEqualTo(napi_env env,napi_callback_info info)263 napi_value JsQuery::LessThanOrEqualTo(napi_env env, napi_callback_info info)
264 {
265     ZLOGD("Query::LessThanOrEqualTo()");
266     auto ctxt = std::make_shared<ValueContext>();
267     ctxt->GetValueSync(env, info);
268     ASSERT_NULL(!ctxt->isThrowError, "LessThanOrEqualTo exit");
269     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
270         "The function LessThanOrEqualTo params must belong one of string number.");
271 
272     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
273     auto strValue = std::get_if<std::string>(&ctxt->vv);
274     if (strValue != nullptr) {
275         query.LessThanOrEqualTo(ctxt->field, *strValue);
276     } else {
277         auto boolValue = std::get_if<bool>(&ctxt->vv);
278         if (boolValue != nullptr) {
279             query.LessThanOrEqualTo(ctxt->field, *boolValue);
280         } else {
281             auto dblValue = std::get_if<double>(&ctxt->vv);
282             if (dblValue != nullptr) {
283                 query.LessThanOrEqualTo(ctxt->field, *dblValue);
284             }
285         }
286     }
287     return ctxt->self;
288 }
289 
IsNull(napi_env env,napi_callback_info info)290 napi_value JsQuery::IsNull(napi_env env, napi_callback_info info)
291 {
292     std::string field;
293     auto ctxt = std::make_shared<ContextBase>();
294     auto input = [env, ctxt, &field](size_t argc, napi_value* argv) {
295         // required 1 arguments :: <field>
296         ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
297             "Parameter error:Mandatory parameters are left unspecified");
298         ctxt->status = JSUtil::GetValue(env, argv[0], field);
299         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
300             "Parameter error:parameters field must be string");
301     };
302     ctxt->GetCbInfoSync(env, info, input);
303     ASSERT_NULL(!ctxt->isThrowError, "IsNull exit");
304     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
305         "Parameter error:IsNull params must be string");
306 
307     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
308     query.IsNull(field);
309     return ctxt->self;
310 }
311 
312 /*
313  * InNumber / NotInNumber
314  * [NOTES] Recommended to use the napi_typedarray_type
315  */
316 enum class NumberType : uint8_t {
317     NUMBER_INT,
318     NUMBER_LONG,
319     NUMBER_DOUBLE,
320     NUMBER_INVALID = 255
321 };
322 struct NumbersContext : public ContextBase {
323     std::string field;
324     std::vector<int> intList;
325     std::vector<int64_t> longList;
326     std::vector<double> doubleList;
327     NumberType innerType = NumberType::NUMBER_INVALID;
328 
GetNumberSyncOHOS::DistributedKVStore::NumbersContext329     void GetNumberSync(napi_env env, napi_callback_info info)
330     {
331         auto input = [this, env](size_t argc, napi_value* argv) {
332             // required 2 arguments :: <field> <value-list>
333             ASSERT_BUSINESS_ERR(this, argc >= 2, Status::INVALID_ARGUMENT,
334                 "Parameter error:Mandatory parameters are left unspecified");
335             status = JSUtil::GetValue(env, argv[0], field);
336             ASSERT_BUSINESS_ERR(this, status == napi_ok, Status::INVALID_ARGUMENT,
337                 "Parameter error:parameters field must be string");
338             bool isTypedArray = false;
339             status = napi_is_typedarray(env, argv[1], &isTypedArray);
340             ZLOGD("arg[1] %{public}s a TypedArray", isTypedArray ? "is" : "is not");
341             if (isTypedArray && (status == napi_ok)) {
342                 napi_typedarray_type type = napi_biguint64_array;
343                 size_t length = 0;
344                 napi_value buffer = nullptr;
345                 size_t offset = 0;
346                 void* data = nullptr;
347                 status = napi_get_typedarray_info(env, argv[1], &type, &length, &data, &buffer, &offset);
348                 ASSERT_BUSINESS_ERR(this, status == napi_ok, Status::INVALID_ARGUMENT,
349                     "Parameter error:parameters numberArray must be array");
350                 if (type < napi_uint32_array) {
351                     status = JSUtil::GetValue(env, argv[1], intList);
352                     innerType = NumberType::NUMBER_INT;
353                 } else if (type == napi_bigint64_array || type == napi_uint32_array) {
354                     status = JSUtil::GetValue(env, argv[1], longList);
355                     innerType = NumberType::NUMBER_LONG;
356                 } else {
357                     status = JSUtil::GetValue(env, argv[1], doubleList);
358                     innerType = NumberType::NUMBER_DOUBLE;
359                 }
360             } else {
361                 bool isArray = false;
362                 status = napi_is_array(env, argv[1], &isArray);
363                 ASSERT_BUSINESS_ERR(this, isArray, Status::INVALID_ARGUMENT,
364                     "Parameter error:parameter isArray must be boolean");
365                 ZLOGD("arg[1] %{public}s a Array, treat as array of double.", isTypedArray ? "is" : "is not");
366                 status = JSUtil::GetValue(env, argv[1], doubleList);
367                 ASSERT_BUSINESS_ERR(this, status == napi_ok, Status::INVALID_ARGUMENT,
368                     "Parameter error:parameters doubleList must be array");
369                 innerType = NumberType::NUMBER_DOUBLE;
370             }
371         };
372         GetCbInfoSync(env, info, input);
373     }
374 };
375 
InNumber(napi_env env,napi_callback_info info)376 napi_value JsQuery::InNumber(napi_env env, napi_callback_info info)
377 {
378     ZLOGD("Query::InNumber()");
379     auto ctxt = std::make_shared<NumbersContext>();
380     ctxt->GetNumberSync(env, info);
381     ASSERT_NULL(!ctxt->isThrowError, "InNumber exit");
382     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
383         "Parameter error:InNumber params must be string or array");
384 
385     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
386     if (ctxt->innerType == NumberType::NUMBER_INT) {
387         query.In(ctxt->field, ctxt->intList);
388     } else if (ctxt->innerType == NumberType::NUMBER_LONG) {
389         query.In(ctxt->field, ctxt->longList);
390     } else if (ctxt->innerType == NumberType::NUMBER_DOUBLE) {
391         query.In(ctxt->field, ctxt->doubleList);
392     }
393     return ctxt->self;
394 }
395 
InString(napi_env env,napi_callback_info info)396 napi_value JsQuery::InString(napi_env env, napi_callback_info info)
397 {
398     ZLOGD("Query::InString()");
399     struct StringsContext : public ContextBase {
400         std::string field;
401         std::vector<std::string> valueList;
402     };
403     auto ctxt = std::make_shared<StringsContext>();
404     auto input = [env, ctxt](size_t argc, napi_value* argv) {
405         // required 2 arguments :: <field> <valueList>
406         ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT,
407             "Parameter error:Mandatory parameters are left unspecified");
408         ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->field);
409         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
410             "Parameter error:parameters filed must be string");
411         ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->valueList);
412         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
413             "Parameter error:parameters valueList must be stringArray");
414     };
415     ctxt->GetCbInfoSync(env, info, input);
416     ASSERT_NULL(!ctxt->isThrowError, "InString exit");
417     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
418         "Parameter error:InString params must be string or array");
419 
420     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
421     query.In(ctxt->field, ctxt->valueList);
422     return ctxt->self;
423 }
424 
NotInNumber(napi_env env,napi_callback_info info)425 napi_value JsQuery::NotInNumber(napi_env env, napi_callback_info info)
426 {
427     ZLOGD("Query::NotInNumber()");
428     auto ctxt = std::make_shared<NumbersContext>();
429     ctxt->GetNumberSync(env, info);
430     ASSERT_NULL(!ctxt->isThrowError, "NotInNumber exit");
431     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
432         "Parameter error:NotInNumber params must be string or numberArray");
433 
434     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
435     if (ctxt->innerType == NumberType::NUMBER_INT) {
436         query.NotIn(ctxt->field, ctxt->intList);
437     } else if (ctxt->innerType == NumberType::NUMBER_LONG) {
438         query.NotIn(ctxt->field, ctxt->longList);
439     } else if (ctxt->innerType == NumberType::NUMBER_DOUBLE) {
440         query.NotIn(ctxt->field, ctxt->doubleList);
441     }
442     return ctxt->self;
443 }
444 
NotInString(napi_env env,napi_callback_info info)445 napi_value JsQuery::NotInString(napi_env env, napi_callback_info info)
446 {
447     ZLOGD("Query::NotInString()");
448     struct StringsContext : public ContextBase {
449         std::string field;
450         std::vector<std::string> valueList;
451     };
452     auto ctxt = std::make_shared<StringsContext>();
453     auto input = [env, ctxt](size_t argc, napi_value* argv) {
454         // required 2 arguments :: <field> <valueList>
455         ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT,
456             "Parameter error:Mandatory parameters are left unspecified");
457         ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->field);
458         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
459             "Parameter error:parameters filed must be string");
460         ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->valueList);
461         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
462             "Parameter error:parameters valueList must be array");
463     };
464     ctxt->GetCbInfoSync(env, info, input);
465     ASSERT_NULL(!ctxt->isThrowError, "NotInString exit");
466     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
467         "Parameter error:NotInString params must be string or stringArray");
468 
469     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
470     query.NotIn(ctxt->field, ctxt->valueList);
471     return ctxt->self;
472 }
473 
Like(napi_env env,napi_callback_info info)474 napi_value JsQuery::Like(napi_env env, napi_callback_info info)
475 {
476     ZLOGD("Query::Like()");
477     struct LikeContext : public ContextBase {
478         std::string field;
479         std::string value;
480     };
481     auto ctxt = std::make_shared<LikeContext>();
482     auto input = [env, ctxt](size_t argc, napi_value* argv) {
483         // required 2 arguments :: <field> <value>
484         ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT,
485             "Parameter error:Mandatory parameters are left unspecified");
486         ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->field);
487         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
488             "Parameter error:parameters filed must be string");
489         ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->value);
490         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
491             "Parameter error:parameters value must be string");
492     };
493     ctxt->GetCbInfoSync(env, info, input);
494     ASSERT_NULL(!ctxt->isThrowError, "Like exit");
495     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
496         "Parameter error:Like params must be string");
497 
498     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
499     query.Like(ctxt->field, ctxt->value);
500     return ctxt->self;
501 }
502 
Unlike(napi_env env,napi_callback_info info)503 napi_value JsQuery::Unlike(napi_env env, napi_callback_info info)
504 {
505     ZLOGD("Query::Unlike()");
506     struct UnlikeContext : public ContextBase {
507         std::string field;
508         std::string value;
509     };
510     auto ctxt = std::make_shared<UnlikeContext>();
511     auto input = [env, ctxt](size_t argc, napi_value* argv) {
512         // required 2 arguments :: <field> <value>
513         ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT,
514             "Parameter error:Mandatory parameters are left unspecified");
515         ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->field);
516         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
517             "Parameter error:parameters field must be string");
518         ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->value);
519         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
520             "Parameter error:parameters value must be string");
521     };
522     ctxt->GetCbInfoSync(env, info, input);
523     ASSERT_NULL(!ctxt->isThrowError, "Unlike exit");
524     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
525         "Parameter error:Unlike params must be string");
526 
527     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
528     query.Unlike(ctxt->field, ctxt->value);
529     return ctxt->self;
530 }
531 
And(napi_env env,napi_callback_info info)532 napi_value JsQuery::And(napi_env env, napi_callback_info info)
533 {
534     ZLOGD("Query::And()");
535     auto ctxt = std::make_shared<ContextBase>();
536     ctxt->GetCbInfoSync(env, info);
537     NAPI_ASSERT(env, ctxt->status == napi_ok, "And failed");
538 
539     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
540     query.And();
541     return ctxt->self;
542 }
543 
Or(napi_env env,napi_callback_info info)544 napi_value JsQuery::Or(napi_env env, napi_callback_info info)
545 {
546     ZLOGD("Query::Or()");
547     auto ctxt = std::make_shared<ContextBase>();
548     ctxt->GetCbInfoSync(env, info);
549     NAPI_ASSERT(env, ctxt->status == napi_ok, "Or failed");
550 
551     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
552     query.Or();
553     return ctxt->self;
554 }
555 
OrderByAsc(napi_env env,napi_callback_info info)556 napi_value JsQuery::OrderByAsc(napi_env env, napi_callback_info info)
557 {
558     ZLOGD("Query::OrderByAsc()");
559     std::string field;
560     auto ctxt = std::make_shared<ContextBase>();
561     auto input = [env, ctxt, &field](size_t argc, napi_value* argv) {
562         // required 1 arguments :: <field>
563         ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
564             "Parameter error:Mandatory parameters are left unspecified");
565         ctxt->status = JSUtil::GetValue(env, argv[0], field);
566         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
567             "Parameter error:parameters field must be string");
568     };
569     ctxt->GetCbInfoSync(env, info, input);
570     ASSERT_NULL(!ctxt->isThrowError, "OrderByAsc exit");
571     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
572         "Parameter error:OrderByAsc params must be string");
573 
574     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
575     query.OrderByAsc(field);
576     return ctxt->self;
577 }
578 
OrderByDesc(napi_env env,napi_callback_info info)579 napi_value JsQuery::OrderByDesc(napi_env env, napi_callback_info info)
580 {
581     ZLOGD("Query::OrderByDesc()");
582     std::string field;
583     auto ctxt = std::make_shared<ContextBase>();
584     auto input = [env, ctxt, &field](size_t argc, napi_value* argv) {
585         // required 1 arguments :: <field>
586         ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
587             "Parameter error:Mandatory parameters are left unspecified");
588         ctxt->status = JSUtil::GetValue(env, argv[0], field);
589         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
590             "Parameter error:parameters field must be string");
591     };
592     ctxt->GetCbInfoSync(env, info, input);
593     ASSERT_NULL(!ctxt->isThrowError, "OrderByDesc exit");
594     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
595         "Parameter error:OrderByDesc params must be string");
596 
597     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
598     query.OrderByDesc(field);
599     return ctxt->self;
600 }
601 
Limit(napi_env env,napi_callback_info info)602 napi_value JsQuery::Limit(napi_env env, napi_callback_info info)
603 {
604     struct LimitContext : public ContextBase {
605         int number;
606         int offset;
607     };
608     auto ctxt = std::make_shared<LimitContext>();
609     auto input = [env, ctxt](size_t argc, napi_value* argv) {
610         // required 2 arguments :: <number> <offset>
611         ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT,
612             "Parameter error:Mandatory parameters are left unspecified");
613         ctxt->status = napi_get_value_int32(env, argv[0], &ctxt->number);
614         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
615             "Parameter error:parameters number must be int");
616         ctxt->status = napi_get_value_int32(env, argv[1], &ctxt->offset);
617         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
618             "Parameter error:parameters offset must be int");
619     };
620     ctxt->GetCbInfoSync(env, info, input);
621     ASSERT_NULL(!ctxt->isThrowError, "Limit exit");
622     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
623         "Parameter error:Limit params must be number");
624 
625     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
626     query.Limit(ctxt->number, ctxt->offset);
627     return ctxt->self;
628 }
629 
IsNotNull(napi_env env,napi_callback_info info)630 napi_value JsQuery::IsNotNull(napi_env env, napi_callback_info info)
631 {
632     ZLOGD("Query::IsNotNull()");
633     std::string field;
634     auto ctxt = std::make_shared<ContextBase>();
635     auto input = [env, ctxt, &field](size_t argc, napi_value* argv) {
636         // required 1 arguments :: <field>
637         ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
638             "Parameter error:Mandatory parameters are left unspecified");
639         ctxt->status = JSUtil::GetValue(env, argv[0], field);
640         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
641             "Parameter error:parameters field must be string");
642     };
643     ctxt->GetCbInfoSync(env, info, input);
644     ASSERT_NULL(!ctxt->isThrowError, "IsNotNull exit");
645     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
646         "Parameter error:IsNotNull params must be string");
647 
648     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
649     query.IsNotNull(field);
650     return ctxt->self;
651 }
652 
BeginGroup(napi_env env,napi_callback_info info)653 napi_value JsQuery::BeginGroup(napi_env env, napi_callback_info info)
654 {
655     ZLOGD("Query::BeginGroup()");
656     auto ctxt = std::make_shared<ContextBase>();
657     ctxt->GetCbInfoSync(env, info);
658     NAPI_ASSERT(env, ctxt->status == napi_ok, "BeginGroup failed");
659 
660     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
661     query.BeginGroup();
662     return ctxt->self;
663 }
664 
EndGroup(napi_env env,napi_callback_info info)665 napi_value JsQuery::EndGroup(napi_env env, napi_callback_info info)
666 {
667     ZLOGD("Query::EndGroup()");
668     auto ctxt = std::make_shared<ContextBase>();
669     ctxt->GetCbInfoSync(env, info);
670     NAPI_ASSERT(env, ctxt->status == napi_ok, "EndGroup failed");
671 
672     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
673     query.EndGroup();
674     return ctxt->self;
675 }
676 
PrefixKey(napi_env env,napi_callback_info info)677 napi_value JsQuery::PrefixKey(napi_env env, napi_callback_info info)
678 {
679     std::string prefix;
680     auto ctxt = std::make_shared<ContextBase>();
681     auto input = [env, ctxt, &prefix](size_t argc, napi_value* argv) {
682         // required 1 arguments :: <prefix>
683         ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
684             "Parameter error:Mandatory parameters are left unspecified");
685         ctxt->status = JSUtil::GetValue(env, argv[0], prefix);
686         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
687             "Parameter error:parameters prefix must be string");
688     };
689     ctxt->GetCbInfoSync(env, info, input);
690     ASSERT_NULL(!ctxt->isThrowError, "PrefixKey exit");
691     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
692         "Parameter error:PrefixKey params must be string");
693 
694     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
695     query.KeyPrefix(prefix);
696     return ctxt->self;
697 }
698 
SetSuggestIndex(napi_env env,napi_callback_info info)699 napi_value JsQuery::SetSuggestIndex(napi_env env, napi_callback_info info)
700 {
701     std::string suggestIndex;
702     auto ctxt = std::make_shared<ContextBase>();
703     auto input = [env, ctxt, &suggestIndex](size_t argc, napi_value* argv) {
704         // required 1 arguments :: <suggestIndex>
705         ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
706             "Parameter error:Mandatory parameters are left unspecified");
707         ctxt->status = JSUtil::GetValue(env, argv[0], suggestIndex);
708         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
709             "Parameter error:parameters suggestIndex must be string");
710     };
711     ctxt->GetCbInfoSync(env, info, input);
712     ASSERT_NULL(!ctxt->isThrowError, "SetSuggestIndex exit");
713     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
714         "Parameter error:SetSuggestIndex params must be string");
715 
716     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
717     query.SetSuggestIndex(suggestIndex);
718     return ctxt->self;
719 }
720 
DeviceId(napi_env env,napi_callback_info info)721 napi_value JsQuery::DeviceId(napi_env env, napi_callback_info info)
722 {
723     std::string deviceId;
724     auto ctxt = std::make_shared<ContextBase>();
725     auto input = [env, ctxt, &deviceId](size_t argc, napi_value* argv) {
726         // required 1 arguments :: <deviceId>
727         ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
728             "Parameter error:Mandatory parameters are left unspecified");
729         ctxt->status = JSUtil::GetValue(env, argv[0], deviceId);
730         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
731             "Parameter error:deviceId must be string");
732     };
733     ctxt->GetCbInfoSync(env, info, input);
734     ASSERT_NULL(!ctxt->isThrowError, "DeviceId exit");
735     ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
736         "Parameter error:DeviceId params must be string");
737 
738     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
739     query.DeviceId(deviceId);
740     return ctxt->self;
741 }
742 
743 // getSqlLike():string
GetSqlLike(napi_env env,napi_callback_info info)744 napi_value JsQuery::GetSqlLike(napi_env env, napi_callback_info info)
745 {
746     auto ctxt = std::make_shared<ContextBase>();
747     ctxt->GetCbInfoSync(env, info);
748     NAPI_ASSERT(env, ctxt->status == napi_ok, "GetSqlLike failed");
749 
750     auto& query = reinterpret_cast<JsQuery*>(ctxt->native)->query_;
751     JSUtil::SetValue(env, query.ToString(), ctxt->output);
752     return ctxt->output;
753 }
754 } // namespace OHOS::DistributedKVStore
755