• 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 "AniRdbError"
17 #include "ani_rdb_error.h"
18 #include "logger.h"
19 
20 #include <algorithm>
21 #include <ani.h>
22 #include <iostream>
23 
24 namespace OHOS {
25 namespace RelationalStoreAniKit {
26 using JsErrorCode = OHOS::RelationalStoreAniKit::JsErrorCode;
27 using namespace OHOS::Rdb;
28 static constexpr JsErrorCode JS_ERROR_CODE_MSGS[] = {
29     { E_NOT_STAGE_MODE, 14801001, "Only supported in stage mode." },
30     { E_DATA_GROUP_ID_INVALID, 14801002, "The data group id is invalid." },
31     { NativeRdb::E_NOT_SELECT, 14800019, "The SQL must be a query statement." },
32     { NativeRdb::E_COLUMN_OUT_RANGE, 14800013, "Column out of bounds." },
33     { NativeRdb::E_INVALID_FILE_PATH, 14800010, "Invalid database path." },
34     { NativeRdb::E_ROW_OUT_RANGE, 14800012, "Row out of bounds." },
35     { NativeRdb::E_NO_ROW_IN_QUERY, 14800018, "No data meets the condition." },
36     { NativeRdb::E_ALREADY_CLOSED, 14800014, "Already closed." },
37     { NativeRdb::E_DATABASE_BUSY, 14800015, "The database does not respond." },
38     { NativeRdb::E_WAL_SIZE_OVER_LIMIT, 14800047, "The WAL file size over default limit." },
39     { NativeRdb::E_GET_DATAOBSMGRCLIENT_FAIL, 14801050, "Failed to get DataObsMgrClient." },
40     { NativeRdb::E_TYPE_MISMATCH, 14800051, "The type of the distributed table does not match." },
41     { NativeRdb::E_SQLITE_FULL, 14800029, "SQLite: The database is full." },
42     { NativeRdb::E_NOT_SUPPORT_THE_SQL, 14800021, "SQLite: Generic error."},
43     { NativeRdb::E_ATTACHED_DATABASE_EXIST, 14800016, "The database is already attached." },
44     { NativeRdb::E_SQLITE_ERROR, 14800021, "SQLite: Generic error." },
45     { NativeRdb::E_SQLITE_CORRUPT, 14800011, "Database corrupted." },
46     { NativeRdb::E_SQLITE_ABORT, 14800022, "SQLite: Callback routine requested an abort." },
47     { NativeRdb::E_SQLITE_PERM, 14800023, "SQLite: Access permission denied." },
48     { NativeRdb::E_SQLITE_BUSY, 14800024, "SQLite: The database file is locked." },
49     { NativeRdb::E_SQLITE_LOCKED, 14800025, "SQLite: A table in the database is locked." },
50     { NativeRdb::E_SQLITE_NOMEM, 14800026, "SQLite: The database is out of memory." },
51     { NativeRdb::E_SQLITE_READONLY, 14800027, "SQLite: Attempt to write a readonly database." },
52     { NativeRdb::E_SQLITE_IOERR, 14800028, "SQLite: Some kind of disk I/O error occurred." },
53     { NativeRdb::E_SQLITE_CANTOPEN, 14800030, "SQLite: Unable to open the database file." },
54     { NativeRdb::E_SQLITE_TOOBIG, 14800031, "SQLite: TEXT or BLOB exceeds size limit." },
55     { NativeRdb::E_SQLITE_CONSTRAINT, 14800032, "SQLite: Abort due to constraint violation." },
56     { NativeRdb::E_SQLITE_MISMATCH, 14800033, "SQLite: Data type mismatch." },
57     { NativeRdb::E_SQLITE_MISUSE, 14800034, "SQLite: Library used incorrectly." },
58     { NativeRdb::E_CONFIG_INVALID_CHANGE, 14800017, "Config changed." },
59     { NativeRdb::E_NOT_SUPPORT, 801, "Capability not support." },
60 };
61 
GetJsErrorCode(int32_t errorCode)62 const std::optional<JsErrorCode> GetJsErrorCode(int32_t errorCode)
63 {
64     auto jsErrorCode = JsErrorCode{ errorCode, -1, "" };
65     auto iter = std::lower_bound(JS_ERROR_CODE_MSGS,
66         JS_ERROR_CODE_MSGS + sizeof(JS_ERROR_CODE_MSGS) / sizeof(JS_ERROR_CODE_MSGS[0]), jsErrorCode,
67         [](const JsErrorCode &jsErrorCode1, const JsErrorCode &jsErrorCode2) {
68             return jsErrorCode1.status < jsErrorCode2.status;
69         });
70     if (iter < JS_ERROR_CODE_MSGS + sizeof(JS_ERROR_CODE_MSGS) / sizeof(JS_ERROR_CODE_MSGS[0]) &&
71         iter->status == errorCode) {
72         return *iter;
73     }
74     return std::nullopt;
75 }
76 
CreateBusinessErrorObj(ani_env * env,int32_t code,const std::string & msg)77 ani_object CreateBusinessErrorObj(ani_env *env, int32_t code, const std::string &msg)
78 {
79     if (env == nullptr) {
80         LOG_ERROR("env is nullptr.");
81         return nullptr;
82     }
83     ani_string message;
84     auto status = env->String_NewUTF8(msg.c_str(), msg.size(), &message);
85     if (ANI_OK != status) {
86         LOG_ERROR("String_NewUTF8 failed, errcode %{public}d.", status);
87         return nullptr;
88     }
89     static const char *businessErrorName = "L@ohos/base/BusinessError;";
90     ani_class cls;
91     status = env->FindClass(businessErrorName, &cls);
92     if (ANI_OK != status) {
93         LOG_ERROR("Not found class '%{public}s' errcode %{public}d.", businessErrorName, status);
94         return nullptr;
95     }
96     ani_method ctor;
97     status = env->Class_FindMethod(cls, "<ctor>", ":V", &ctor);
98     if (ANI_OK != status) {
99         LOG_ERROR("Not found ctor of '%{public}s' errcode %{public}d.", businessErrorName, status);
100         return nullptr;
101     }
102     ani_object businessErrorObject;
103     status = env->Object_New(cls, ctor, &businessErrorObject);
104     if (ANI_OK != status) {
105         LOG_ERROR("Can not create business error errcode %{public}d.", status);
106         return nullptr;
107     }
108     status = env->Object_SetFieldByName_Double(businessErrorObject, "code", code);
109     if (ANI_OK != status) {
110         LOG_ERROR("Can not set business error code errcode %{public}d.", status);
111         return nullptr;
112     }
113     status = env->Object_SetPropertyByName_Ref(businessErrorObject, "message", message);
114     if (ANI_OK != status) {
115         LOG_ERROR("Can not set business error message errcode %{public}d.", status);
116         return businessErrorObject;
117     }
118 
119     return businessErrorObject;
120 }
121 
GetAniBusinessError(ani_env * env,int32_t errorCode)122 ani_object GetAniBusinessError(ani_env *env, int32_t errorCode)
123 {
124     auto errInfo = GetJsErrorCode(errorCode);
125     auto code_ = E_INNER_ERROR;
126     auto msg_ = "Inner error. Inner code is " + std::to_string(errorCode % E_INNER_ERROR);
127     if (errInfo.has_value()) {
128         auto aniError = errInfo.value();
129         code_ = aniError.jsCode;
130         msg_ = aniError.message;
131     }
132 
133     return CreateBusinessErrorObj(env, code_, msg_);
134 }
135 
ThrowBusinessError(ani_env * env,int32_t status)136 void ThrowBusinessError(ani_env *env, int32_t status)
137 {
138     if (NativeRdb::E_OK == status) {
139         return;
140     }
141     if (env == nullptr) {
142         LOG_ERROR("env is nullptr.");
143         return;
144     }
145     ani_object businessError = GetAniBusinessError(env, status);
146     if (nullptr == businessError) {
147         LOG_ERROR("Can not get business error.");
148     } else {
149         auto status = env->ThrowError(static_cast<ani_error>(businessError));
150         if (status != ANI_OK) {
151             LOG_ERROR("ThrowError err %{public}d.", status);
152         }
153     }
154 }
155 
ThrowBusinessError(ani_env * env,int32_t status,std::string message)156 void ThrowBusinessError(ani_env *env, int32_t status, std::string message)
157 {
158     if (OK == status) {
159         return;
160     }
161     if (env == nullptr) {
162         LOG_ERROR("env is nullptr.");
163         return;
164     }
165     ani_object businessError = CreateBusinessErrorObj(env, status, message);
166     if (nullptr == businessError) {
167         LOG_ERROR("Can not get business error.");
168     } else {
169         auto status = env->ThrowError(static_cast<ani_error>(businessError));
170         if (status != ANI_OK) {
171             LOG_ERROR("ThrowError err %{public}d.", status);
172         }
173     }
174 }
175 
176 } // namespace RelationalStoreAniKit
177 } // namespace OHOS
178 
179