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