• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #define LOG_TAG "AniRdbStore"
17 #include <ani.h>
18 #include <iostream>
19 #include <string>
20 
21 #include "logger.h"
22 #include "rdb_errno.h"
23 #include "ani_utils.h"
24 #include "ani_result_set.h"
25 #include "ani_rdb_error.h"
26 #include "ani_rdb_store_helper.h"
27 #include "ani_rdb_predicates.h"
28 #include "rdb_utils.h"
29 
30 namespace OHOS {
31 namespace RelationalStoreAniKit {
32 
33 using namespace OHOS::NativeRdb;
34 using namespace OHOS::Rdb;
35 
ConvertBindArgs(ani_env * env,ani_object args,std::vector<ValueObject> & bindArgs,bool isOptional)36 bool ConvertBindArgs(ani_env *env, ani_object args, std::vector<ValueObject> &bindArgs, bool isOptional)
37 {
38     if (env == nullptr) {
39         LOG_ERROR("env is nullptr.");
40         return false;
41     }
42     if (isOptional) {
43         ani_boolean isUndefined = true;
44         env->Reference_IsUndefined(args, &isUndefined);
45         if (isUndefined) {
46             bindArgs.clear();
47             return true;
48         }
49     }
50     std::vector<ani_ref> valRefs;
51     UnionAccessor array2Ref(env, args);
52     bool convertArrayOk = array2Ref.TryConvert(valRefs);
53     if (!convertArrayOk) {
54         LOG_ERROR("conver array fail");
55         return false;
56     }
57     for (const auto& ref : valRefs) {
58         ani_object valObject = static_cast<ani_object>(ref);
59         ValueObject valueObject;
60         UnionAccessor unionAccessor(env, valObject);
61         bool convertOk = false;
62         convertOk = unionAccessor.TryConvertVariant(valueObject.value);
63         if (convertOk) {
64             bindArgs.push_back(std::move(valueObject));
65         } else {
66             LOG_ERROR("conver ValueObject fail");
67             return false;
68         }
69     }
70     return true;
71 }
72 
ExecuteSqlSync(ani_env * env,ani_object object,ani_string sql,ani_object args)73 void ExecuteSqlSync(ani_env *env, ani_object object, ani_string sql, ani_object args)
74 {
75     if (env == nullptr) {
76         LOG_ERROR("env is nullptr.");
77         return;
78     }
79 
80     std::vector<ValueObject> bindArgs;
81 
82     bool convertOk = ConvertBindArgs(env, args, bindArgs, true);
83     if (!convertOk) {
84         LOG_ERROR("args conver fail");
85         ThrowBusinessError(env, E_PARAM_ERROR, "Unknown parameters.");
86         return;
87     }
88 
89     auto proxy = AniObjectUtils::Unwrap<RdbStoreProxy>(env, object);
90     if (proxy == nullptr || proxy->nativeRdb == nullptr) {
91         LOG_ERROR("RdbStore should be initialized properly.");
92         ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized.");
93         return;
94     }
95     auto sqlStr = AniStringUtils::ToStd(env, sql);
96     auto status = proxy->nativeRdb->ExecuteSql(sqlStr, bindArgs);
97     ThrowBusinessError(env, status);
98 }
99 
BeginTransaction(ani_env * env,ani_object object)100 void BeginTransaction(ani_env *env, ani_object object)
101 {
102     if (env == nullptr) {
103         LOG_ERROR("env is nullptr.");
104         return;
105     }
106     auto proxy = AniObjectUtils::Unwrap<RdbStoreProxy>(env, object);
107     if (proxy == nullptr || proxy->nativeRdb == nullptr) {
108         LOG_ERROR("RdbStore should be initialized properly.");
109         ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized.");
110         return;
111     }
112     auto status = proxy->nativeRdb->BeginTransaction();
113     ThrowBusinessError(env, status);
114 }
115 
Commit(ani_env * env,ani_object object)116 void Commit(ani_env *env, ani_object object)
117 {
118     if (env == nullptr) {
119         LOG_ERROR("env is nullptr.");
120         return;
121     }
122     auto proxy = AniObjectUtils::Unwrap<RdbStoreProxy>(env, object);
123     if (proxy == nullptr || proxy->nativeRdb == nullptr) {
124         LOG_ERROR("RdbStore should be initialized properly.");
125         ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized.");
126         return;
127     }
128     auto status = proxy->nativeRdb->Commit();
129     ThrowBusinessError(env, status);
130 }
131 
RollBack(ani_env * env,ani_object object)132 void RollBack(ani_env *env, ani_object object)
133 {
134     if (env == nullptr) {
135         LOG_ERROR("env is nullptr.");
136         return;
137     }
138     auto proxy = AniObjectUtils::Unwrap<RdbStoreProxy>(env, object);
139     if (proxy == nullptr || proxy->nativeRdb == nullptr) {
140         LOG_ERROR("RdbStore should be initialized properly.");
141         ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized.");
142         return;
143     }
144     auto status = proxy->nativeRdb->RollBack();
145     ThrowBusinessError(env, status);
146 }
147 
BatchInsert(ani_env * env,ani_object object,ani_string tableName,ani_object values)148 ani_double BatchInsert(ani_env *env, ani_object object, ani_string tableName, ani_object values)
149 {
150     if (env == nullptr) {
151         LOG_ERROR("env is nullptr.");
152         return 0;
153     }
154     auto proxy = AniObjectUtils::Unwrap<RdbStoreProxy>(env, object);
155     if (proxy == nullptr || proxy->nativeRdb == nullptr) {
156         LOG_ERROR("RdbStore should be initialized properly.");
157         ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized.");
158         return 0;
159     }
160     auto name = AniStringUtils::ToStd(env, tableName);
161     std::vector<ani_ref> valRefs;
162     UnionAccessor array2Ref(env, values);
163     array2Ref.TryConvert(valRefs);
164     ValuesBuckets vbs;
165     for (const auto& ref : valRefs) {
166         ani_object recordObj = static_cast<ani_object>(ref);
167         UnionAccessor recordAccessor(env, recordObj);
168         ValuesBucket valuesBucket;
169         recordAccessor.TryConvert(valuesBucket);
170         vbs.Put(valuesBucket);
171     }
172     auto [status, ret] = proxy->nativeRdb->BatchInsert(name, vbs);
173     ThrowBusinessError(env, status);
174     return ret;
175 }
176 
DeleteSync(ani_env * env,ani_object object,ani_object predicates)177 ani_double DeleteSync(ani_env *env, ani_object object, ani_object predicates)
178 {
179     if (env == nullptr) {
180         LOG_ERROR("env is nullptr.");
181         return 0;
182     }
183     auto proxy = AniObjectUtils::Unwrap<RdbStoreProxy>(env, object);
184     if (proxy == nullptr || proxy->nativeRdb == nullptr) {
185         LOG_ERROR("RdbStore should be initialized properly.");
186         ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized.");
187         return 0;
188     }
189     auto nativePredicates = AniObjectUtils::Unwrap<PredicatesProxy>(env, predicates);
190     if (nativePredicates == nullptr || nativePredicates->predicates == nullptr) {
191         LOG_ERROR("Predicates should be initialized properly.");
192         ThrowBusinessError(env, E_INNER_ERROR, "Predicates uninitialized.");
193         return 0;
194     }
195     int rows = 0;
196     auto status = proxy->nativeRdb->Delete(rows, *(nativePredicates->predicates));
197     ThrowBusinessError(env, status);
198     return rows;
199 }
200 
DeleteShareSync(ani_env * env,ani_object object,ani_string tableName,ani_object dataSharePredicates)201 ani_double DeleteShareSync(ani_env *env, ani_object object, ani_string tableName, ani_object dataSharePredicates)
202 {
203     if (env == nullptr) {
204         LOG_ERROR("env is nullptr.");
205         return 0;
206     }
207     auto proxy = AniObjectUtils::Unwrap<RdbStoreProxy>(env, object);
208     if (proxy == nullptr || proxy->nativeRdb == nullptr) {
209         LOG_ERROR("RdbStore should be initialized properly.");
210         ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized.");
211         return 0;
212     }
213 
214     std::string name = AniStringUtils::ToStd(env, tableName);
215 
216     auto cppDataSharePredicates = AniObjectUtils::Unwrap<DataShare::DataShareAbsPredicates>(env, dataSharePredicates);
217     if (cppDataSharePredicates == nullptr) {
218         LOG_ERROR("Predicates should be initialized properly.");
219         ThrowBusinessError(env, E_INNER_ERROR, "Predicates uninitialized.");
220         return 0;
221     }
222     RdbPredicates rdbPredicates = RdbDataShareAdapter::RdbUtils::ToPredicates(*cppDataSharePredicates, name);
223     int rows = 0;
224     auto status = proxy->nativeRdb->Delete(rows, rdbPredicates);
225     ThrowBusinessError(env, status);
226     return rows;
227 }
228 
QuerySqlSync(ani_env * env,ani_object object,ani_string sql,ani_object args)229 ani_object QuerySqlSync(ani_env *env, ani_object object, ani_string sql, ani_object args)
230 {
231     if (env == nullptr) {
232         LOG_ERROR("env is nullptr.");
233         return nullptr;
234     }
235     std::vector<ValueObject> bindArgs;
236     auto sqlStr = AniStringUtils::ToStd(env, sql);
237 
238     if (!ConvertBindArgs(env, args, bindArgs, true)) {
239         LOG_ERROR("args conver fail");
240         return nullptr;
241     }
242     auto proxy = AniObjectUtils::Unwrap<RdbStoreProxy>(env, object);
243     if (proxy == nullptr || proxy->nativeRdb == nullptr) {
244         ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized.");
245         return nullptr;
246     }
247     auto resultsetProxy = new ResultSetProxy();
248     if (resultsetProxy == nullptr) {
249         ThrowBusinessError(env, E_INNER_ERROR, "Proxy is nullptr.");
250         return nullptr;
251     }
252     resultsetProxy->resultset = proxy->nativeRdb->QueryByStep(sqlStr, bindArgs);
253     if (resultsetProxy->resultset == nullptr) {
254         delete resultsetProxy;
255         ThrowBusinessError(env, E_INNER_ERROR, "QueryByStep returned nullptr.");
256         return nullptr;
257     }
258 
259     static const char *namespaceName = "L@ohos/data/relationalStore/relationalStore;";
260     static const char *className = "LResultSetInner;";
261     static const char *initFinalizer = "initFinalizer";
262     ani_object obj = AniObjectUtils::Create(env, namespaceName, className);
263     if (nullptr == obj) {
264         delete resultsetProxy;
265         ThrowBusinessError(env, E_INNER_ERROR, "Create ResultSet failed.class: LResultSetInner;");
266         return nullptr;
267     }
268     ani_status status = AniObjectUtils::Wrap(env, obj, resultsetProxy);
269     if (ANI_OK != status) {
270         delete resultsetProxy;
271         ThrowBusinessError(env, E_INNER_ERROR, "Wrap ResultSet  failed.class: LResultSetInner;");
272         return nullptr;
273     }
274     status = AniObjectUtils::CallObjMethod(env, namespaceName, className, initFinalizer, obj);
275     if (ANI_OK != status) {
276         ThrowBusinessError(env, E_INNER_ERROR, "init ResultSet finalizer failed.class: LResultSetInner;");
277         return nullptr;
278     }
279     return obj;
280 }
281 
RdbStoreInit(ani_env * env)282 ani_status RdbStoreInit(ani_env *env)
283 {
284     if (env == nullptr) {
285         LOG_ERROR("env is nullptr.");
286         return ANI_ERROR;
287     }
288     static const char *namespaceName = "L@ohos/data/relationalStore/relationalStore;";
289     ani_namespace ns;
290     if (ANI_OK != env->FindNamespace(namespaceName, &ns)) {
291         LOG_ERROR("Not found '%{public}s'", namespaceName);
292         return ANI_ERROR;
293     }
294 
295     static const char *clsName = "LRdbStoreInner;";
296     ani_class cls;
297     if (ANI_OK != env->Namespace_FindClass(ns, clsName, &cls)) {
298         LOG_ERROR("Not found '%{public}s'", clsName);
299         return ANI_ERROR;
300     }
301 
302     std::array methods = {
303         ani_native_function {"batchInsertSync", nullptr, reinterpret_cast<void *>(BatchInsert)},
304         ani_native_function {"beginTransaction", nullptr, reinterpret_cast<void *>(BeginTransaction)},
305         ani_native_function {"commit", ":V", reinterpret_cast<void *>(Commit)},
306         ani_native_function {"rollBack", nullptr, reinterpret_cast<void *>(RollBack)},
307         ani_native_function {"executeSqlSync", nullptr, reinterpret_cast<void *>(ExecuteSqlSync)},
308         ani_native_function {"deleteSync", nullptr, reinterpret_cast<void *>(DeleteSync)},
309         ani_native_function {"deleteShareSync", nullptr, reinterpret_cast<void *>(DeleteShareSync)},
310         ani_native_function {"querySqlSync", nullptr, reinterpret_cast<void *>(QuerySqlSync)},
311     };
312     if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) {
313         LOG_ERROR("Cannot bind native methods to '%{public}s'", clsName);
314         return ANI_ERROR;
315     }
316     return ANI_OK;
317 }
318 
319 
320 } // namespace RelationalStoreAniKit
321 } // namespace OHOS
322 
323